Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在F#中编写可变函数,模拟类似的Haskell解决方案?_F#_Variadic Functions - Fatal编程技术网

如何在F#中编写可变函数,模拟类似的Haskell解决方案?

如何在F#中编写可变函数,模拟类似的Haskell解决方案?,f#,variadic-functions,F#,Variadic Functions,如何(如果有的话)模拟变量函数(而不是方法),以便编写 sum 1 2 3 sum 1 2 3 4 5 sum 1 2 3 4 5 6 7 // etc. 上面的代码只是一个示例——显然,如果我必须总结一个列表的话 [ 1; 2 ; 3] |> List.sum 这是一个更好的方法 但是,我正在寻找结构类似的解决方案,如 同样重要的是,函数调用和参数值的常规语法保持不变。所以 sum 1 2 3 vs 这实际上意味着 let sum ([<ParamArray>] ar

如何(如果有的话)模拟变量函数(而不是方法),以便编写

sum 1 2 3
sum 1 2 3 4 5
sum 1 2 3 4 5 6 7
// etc.
上面的代码只是一个示例——显然,如果我必须总结一个列表的话

[ 1; 2 ; 3] |> List.sum 
这是一个更好的方法

但是,我正在寻找结构类似的解决方案,如

同样重要的是,函数调用和参数值的常规语法保持不变。所以

sum 1 2 3
vs

这实际上意味着

let sum ([<ParamArray>] arr) = ...
let sum([]arr)=。。。
在这种特殊情况下不需要

所有这些的动机:我正在探索F#的类型系统和语法的外部边缘。我充分意识到我可能已经越过了可能的界限

PS:我的具体想法(我在这里没有描述)也可以完全不同地解决——所以我知道,所以我已经做了。 因此,我的问题不是:如何以不同的方式解决这个问题,而是如何像Haskell那样从结构上解决这个问题


PPS:如果可以使整个解决方案递归,则会产生双重业力点。

如注释中所述,您可以使用F#中的
paramary
属性,这将允许您使用多个参数调用函数-尽管您必须使用.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非常有用。

您所说的是函数,而不是方法。因此,
ParamArray
不是一个选项

链接的Haskell代码基于推断的结果类型

下面是一种基于F#中推断的结果类型进行解析的方法:

类型T=T,带
静态成员内联($)(T,r:'T->'T)=乐趣a b->a+b
静态成员内联($)(T,r:'T->'T->'T)=有趣的abc->a+b+c
静态成员内联($)(T,r:'T->'T->'T->'T->'T->'T)=乐趣a b c d->a+b+c+d
让内联求和(x:'a):'r=(T$Unchecked.defaultof'rest)=乐趣(a:'T)->(+)a>>求和
设x:int=2和3
设y:int=sum 2 3 4
设z:int=sum 2 3 4 5
设d:十进制=总和2M 3M 4M
设a b c=a*b*c
设res2=mult3数3(和34)(和23)
设res3=mult3数字3(和3 4 5 11 13 20)10

您也可以看看这个。

请参阅此处的参数数组:@scrwtp的可能重复项:我已经扩展了这个问题。我希望现在这不是一个重复的问题,这一点更加清楚。至少不是你的链接。非常有趣的问题。更新后,很明显这不是重复的。我不明白为什么会被否决。@robkuz:很公平。似乎每个人都在玩这个游戏,所以我的案子就到此为止。我不知道为什么这个被否决了,因为它确实回答了这个问题。虽然我认为这只适用于固定数量的重载,对吗?(我不建议这样写F#,但这是一个单独的主题。)我认为你上一次的编辑刚刚杀死了1000000只小猫。但它能做到这一点令人惊讶。@TomasPetricek在尝试使用超过10个参数时,它还杀死了我的编译器;)令人印象深刻你我不能说我真的理解发生了什么。这段代码在VS2015的调试版本中运行时抛出了一个
TypeInitializationException
。但它在发布版本中也能工作。我把“探索F型系统的边界”称为“robkuz”,这很有道理。尽管我仍然认为重要的是,在实践中,任何人都不应该真的这样做:-)。特别是在问“我如何从F#中的Haskell做XYZ”的问题时,情况更是如此,因为他们经常将人们引向错误的方向(在另一种语言中盲目使用一种语言的技术从来都不是一个好主意)。当然,纯粹出于好奇的问题是个例外!
List.sum [1; 2; 3 ]
List.sum [1; 2; 3; 4; 5 ]
List.sum [1; 2; 3; 4; 5; 6; 7 ]
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
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