2012-02-23 81 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