我试图更好地理解功能编码方式,并且只写了一个小程序来打印用户输入数字的阶乘:
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
[<EntryPoint>]
let main argv = (dropStrArr >> factComp) argv
这个工作正常但后来我认为main
可以纯粹由作文定义并尝试:
let main = dropStrArr >> factComp
我认为它会起作用,但是虽然它会编译,但它会在运行时立即退出。
这两种情况有不同的类型:
unit -> int
当main用其参数定义时,相对于
(unit -> int)
使用作文时。
我可能对类型系统缺失了,所以我的问题是为什么不能通过合成来定义主要的?
答案 0 :(得分:5)
简短的回答是,在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<int, int>
{
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
而且不再有a static main method as is required。