我试图更好地理解功能编码方式,并且只写了一个小程序来打印用户输入数字的阶乘:
open System let fact n = let rec factiter init acc = if init = 0 then acc else factiter (init - 1) init*acc factiter n 1 let dropStrArr (argv: string []) = ignore argv let factComp = Console.ReadLine >> Int32.Parse >> fact >> Console.WriteLine >> fun () -> 0 [] let main argv = (dropStrArr >> factComp) argv
这工作正常,但后来我认为main
可以纯粹由组成定义并尝试:
let main = dropStrArr >> factComp
我认为它可以工作,但是虽然它编译,它只是在运行时立即退出.
在两种情况下有不同的类型:
unit -> int
当使用其参数定义main (unit -> int)
时,与使用合成时相比
.
我可能错过了关于类型系统的问题,所以我的问题是为什么不能通过这里的组合来定义主要的?
简短的回答是,在F#中编写无点样式会产生影响.
部分应用,编译FSharpFunc
并随后调用的函数Invoke
.
为了显示:
let mul a b = a + b let mul2 = mul 2 //point-free let mul2P a = mul 2 a //pointed
mul2P
看起来像你期望的那样(在等效的C#中)
static int mul2P(int a) { return mul(2, a); }
而mul2
成为
class mul2Impl : FSharpFunc{ public int a; mul2Impl(int a) { this.a = a; } public override int Invoke(int b) { return mul(this.a, b); } }
所以,当你写let main argv
它成为这只是调用其他两个简单的静态方法FSharpFunc
与
factComp.Invoke(dropStrArr.Invoke(argv));
但是当你编写它时,main
就变成了一个FSharpFunc
并且不再需要一个静态主方法.