何时在方法声明中使用括号?

And*_*eiM 2 f#

如果我声明一个没有参数的方法,然后调用它(在F#-interactive中),那么我得到预期的行为:屏幕上显示"test".

let somefn() = 
    printfn "test"
> 
val somefn : unit -> unit

> somefn();;
test
val it : unit = ()
Run Code Online (Sandbox Code Playgroud)

但是,如果我声明没有括号的方法,那么我会得到一些不同的行为:

let somefn = 
    printfn "test"
> 
test
val somefn : unit = ()

> somefn;;
val it : unit = ()

> somefn();;

  somefn();;
  ^^^^^^

C:\...\Local\Temp\stdin(4,1): error FS0003: This value is not a function and cannot be applied.
Run Code Online (Sandbox Code Playgroud)

所以我不明白:

  1. 为什么没有参数的方法声明与参数不同?
  2. 当我没有括号声明时,我收到了消息:val somefn:unit =().什么是单位=()?我现在刚刚宣布了什么?什么样的实体是somefn现在呢?
  3. 很明显,现在有一个名为somefn的实体,它指向一些可执行代码.我该如何执行该代码?我可以声明somefn作为结构或其他东西的成员并从那里执行它吗?

The*_*Fox 7

上面的评论回答了这个问题,但我会补充一些细节.

定义函数时,每个参数实际上只与一个案例匹配.例如,您可以写:

let somefn 0 = 1
Run Code Online (Sandbox Code Playgroud)

这个功能的类型是int -> int.第一个参数被推断为a int,但是这会生成警告,因为还有其他未匹配的整数.somefn 0返回1,但somefn 1抛出异常"The match cases were incomplete".

该类型unit只有一个值:().它实际上是输入或函数输出的"无"值.它有一个模式匹配,看起来与值完全相同(就像[]空列表一样),这就是为什么你可以使用单元参数添加单元参数().这些功能都完全相同:

let somefn () = ()
let somefn (x:unit) = ()
let somefn (_:unit) = ()
Run Code Online (Sandbox Code Playgroud)

当您编写一个不带任何参数的函数时,您只需添加一个unit参数,使其成为函数而不是值,因此您可以延迟执行.只是为了让点回家,你甚至可以添加多个unit参数,尽管你永远不需要这样做:

let somefn () () = ()
// unit -> unit -> unit
Run Code Online (Sandbox Code Playgroud)