簡體   English   中英

如何在F#中編寫一個可變函數來模擬類似的Haskell解決方案?

[英]How to write a variadic function in F# emulating a similar Haskell solution?

我怎么能(如果有的話)模擬可變參數函數 (不是方法)以便我可以寫

sum 1 2 3
sum 1 2 3 4 5
sum 1 2 3 4 5 6 7
// etc.

上面的代碼只是作為一個例子 - 顯然如果我必須總結一個列表

[ 1; 2 ; 3] |> List.sum 

是一個更好的方式。

但是,我正在尋找像Haskell解決方案這樣的結構相似的解決方案

同樣重要的是函數調用和參數值的正常語法保持不變。 所以

sum 1 2 3

VS

sum(1, 2, 3)

這實際上意味着

let sum ([<ParamArray>] arr) = ...

在這個特定的情況下不需要。

所有這一切的動機:我正在探索F#的類型系統和語法的外邊緣。 而且我完全意識到我可能已經越過了可能已經存在的邊界。

PS:我的具體想法(我在這里沒有描述)也可以完全不同的方式解決 - 所以我知道,所以我已經完成了。 因此我的問題不是:如何以不同的方式解決這個問題,但如何在結構上像Haskell一樣解決這個問題。

PPS:Double Karma-Points如果你可以使整個解決方案遞歸。

你說功能,而不是方法。 所以ParamArray不是一個選擇。

您鏈接的Haskell代碼基於推斷的結果類型。

這是基於F#中的推斷結果類型解決的一種方法:

type T = T with
    static member inline ($) (T, r:'t->'t        ) = fun a b     -> a + b
    static member inline ($) (T, r:'t->'t->'t    ) = fun a b c   -> a + b + c
    static member inline ($) (T, r:'t->'t->'t->'t) = fun a b c d -> a + b + c + d

let inline sum (x:'a) :'r = (T $ Unchecked.defaultof<'r>) x

let x:int = sum 2 3 
let y:int = sum 2 3 4
let z:int = sum 2 3 4 5
let d:decimal = sum 2M 3M 4M

let mult3Numbers a b c = a * b * c
let res2 = mult3Numbers 3 (sum 3 4  ) 10
let res3 = mult3Numbers 3 (sum 3 4 5) 10

UPDATE

上面的代碼不再適用於F#4.1(參見注釋),但這是一個更好的例子,帶有n(無限制)參數的遞歸多變量函數:

type T = T with
    static member        ($) (T, _:int    ) = (+)
    static member        ($) (T, _:decimal) = (+)

let inline sum (i:'a) (x:'a) :'r = (T $ Unchecked.defaultof<'r>) i x

type T with
    static member inline ($) (T, _:'t-> 'rest) = fun (a:'t) -> (+) a >> sum


let x:int = sum 2 3 
let y:int = sum 2 3 4
let z:int = sum 2 3 4 5
let d:decimal = sum 2M 3M 4M

let mult3Numbers a b c = a * b * c
let res2 = mult3Numbers 3 (sum 3 4) (sum 2 2 3 3)
let res3 = mult3Numbers 3 (sum 3 4 5 11 13 20) 10

你也可以看看這個polyvariadic折疊

正如評論中所提到的,您可以在F#中使用ParamArray屬性,這將允許您使用多個參數調用函數 - 盡管您必須使用.NET表示法並寫入sum(1,2,3,4,5,6)

也就是說,我可能不會在實踐中這樣做。 如果您正在編寫一個包含未知數量值的輸入的函數,那么使用列表可能是更好的設計:

List.sum [1; 2; 3 ]
List.sum [1; 2; 3; 4; 5 ]
List.sum [1; 2; 3; 4; 5; 6; 7 ]

這只是幾個字符,它更好地模擬你正在解決的問題 - 至少,基於你在這里發布的玩具示例。

在不知道你實際解決的問題是什么的情況下很難給出一個好的答案。 但總的來說,我認為列出一個很好的F#友好默認值。 在某些情況下使用ParamArray非常有用,對於C#interop也很有用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM