我试图更好地理解函数式编码方式,并编写了一个小程序来打印回用户输入数字的阶乘:
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)
使用组合时。我可能缺少类型系统,所以我的问题是为什么不能在这里通过组合定义 main ?
最佳答案
简短的回答是在 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 .
关于f# - 在 F# 中通过组合定义 EntryPoint,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41604526/