如何在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