我如何(如果有的话)模拟可变函数(不是方法),以便我可以编写
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
与
sum(1, 2, 3)
这实际上意味着
let sum ([<ParamArray>] arr) = ...
在这种特定情况下不需要。
所有这些的动机:我正在探索F#的类型系统和语法的外部边缘。我完全意识到,我可能已经跨越了可能的界限。
PS:我的具体想法(在此未描述)也可以完全不同地解决-我知道,所以我已经做到了。因此,我的问题不是:如何能以不同的方式解决这个问题,而又如何像Haskell那样在结构上解决呢?
PPS:如果您可以使整个解决方案递归,则加倍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
更新
上面的代码从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
您还可以查看此多变量折叠。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句