2012-02-23 105 views
1

/组合子我有功能接受相同类型的输入时,不同类型的列表作为输出功能合并在fsharp

[ f_i : Mytype -> res:Sometype_i ] 

哪些操作可以将它们合并到以下类型的一个函数?

f : Mytype -> \Product_i Mytype_i 

期同,如果我有函数返回同一类型

[ f_i : Mytype_i -> res:Sometype ] 

其列表操作可将它们合并到以下类型的功能之一?

f : \Product_i Mytype_i -> Mytype list 

这将是一些规范的“preCombinator”或“postCombinator”。 (我想它在FP中有一个名字..)

+2

我不明白你意思是 - 你的语法不是F# - 特别是'func'不是F#关键字,也是惯用的F#写入'int list'而不是'[int]'这很容易混淆(我想这就是你的意思) – 2012-02-23 10:28:43

+0

抱歉,我是不太熟悉fsharp语法。我想你必须删除func才能输出类型为fsahrp的输出。我会编辑它。 – nicolas 2012-02-23 10:32:41

+0

如果你使用F#interactive,它会打印出你的类型签名,这可以帮助你解决这样的问题,如果你使用编译器 – 2012-02-23 10:35:10

回答

3

你的第一个问题的答案是,你不能这样做一般。列表是具有动态长度的数据结构,但是生成的元组的长度在编译时必须是静态的。 (你可以使用反射来构造结果元组,并将其用作obj,但那不是很有用。)

在第二种情况下,您想将函数列表转换为函数返回列表,这可以完成(两者都有动态长度)。你可以写类似:

let funcs = 
    [ (fun n -> n + 1) 
    (fun n -> n * 2) ] 

let merged = 
    funcs |> List.fold (fun agg f -> 
    fun inp -> (f inp)::(agg inp)) (fun _ -> []) 

的基本操作(传递给fold)是一个函数,TInp -> TOut list类型和功能TInp -> TOut的功能,并将它们组合成返回一个较长的列表的功能。所以,你也可以这样写:

// val addResult : ('a -> 'b list) -> ('a -> 'b) -> 'a -> 'b list 
let addResult agg f inp = (f inp)::(agg inp) 

// val merge : ('a -> 'b) list -> ('a -> 'b list) 
let merge funcs = funcs |> List.fold addResult (fun _ -> []) 
+0

yes也可以使用'--sigfile'选项我想我可以自己写,但我认为会有一些内置的组合器。至少它很教学! – nicolas 2012-02-23 10:35:19

+0

非常真实,类型本身正在改变。只有通过类型化的'obj'世界才有可能......有趣的是,在这一点上我已经投入了它,因为我进入了反思,自动为我的记录字段创建了setter。现在,如果我想从单个领域创建者为我的整个结构创建一个setter,我无法静态执行此操作。这是我见过很多次混合的同样的问题。反思世界打破了类型。 – nicolas 2012-02-23 10:41:28

+0

这是因为反射来自更高的“运行时级别”,并且我们在运行时“级别0”的类型环境中使用运行时间“级别-1”。 Type Provider很好地解决了这个问题:我们可以表达这个问题,因为我们需要动态地图,所以它本质上是“level -1”,但是我们运行它来为类型提供“level 0”,并且这个级别通过自己的类型生成混合类型生成级别,这是“级别-1”,使用这种类型,即“级别0” – nicolas 2012-02-23 10:45:33

3

的替代托马斯与在同一顺序返回功能的额外奖金的第二个问题的解决方案,因为他们最初

let funcs = 
    [ (fun n -> n + 1) 
    (fun n -> n * 2) ] 

let merged = fun input -> funcs |> List.map (fun f -> f input) 
+0

非常清晰和简洁.. – nicolas 2012-02-23 11:50:16