A.R*_*.R. 3 f# type-inference unit-type
如果我有以下功能:
let myFunc x y =
if y = 0 then 1
x
Run Code Online (Sandbox Code Playgroud)
我收到错误:
Program.fs(58,17): error FS0001: This expression was expected to have type
unit
but here has type
int
Run Code Online (Sandbox Code Playgroud)
为什么编译器期望'unit'而不是int?
值得补充的是,这不仅仅是一个属性if.F#是一种基于表达式的语言,这意味着几乎每一段代码(除了类型声明和一些例外)都是一个表达式,可以计算出一些结果.实际上,F#不会调用ifif 语句,而是调用if 表达式.
这意味着您可以if在意想不到的地方使用.例如,这可能很有用:
x/2 + (if x%2=0 then 0 else 1)
Run Code Online (Sandbox Code Playgroud)
正如Garry已经解释的那样,如果你省略了else,那么表达式仍然需要返回一些东西 - 如果结果是a int,那么它就没有意义(编译器选择哪个数字?),所以它需要结果是类型unit,是一种表示"无结果"的特殊类型.
该unit类型也是所有命令函数(例如printf)或所有不在逻辑上返回任何值(赋值或例如循环)的表达式的结果.这意味着如果你写:
if x > 0 then printfn "Big!"
Run Code Online (Sandbox Code Playgroud)
...然后表达式是良好类型的,因为printfn "Big!"有一个返回类型unit,并且隐式添加的else分支也返回unit.您可以unit直接手动创建类型的值(类型只有一个值),因此上面实际上对应于:
if x > 0 then printfn "Big!" else ()
Run Code Online (Sandbox Code Playgroud)
从C#的角度来看,读取if .. then .. else条件运算符更有意义:
x/2 + (x%2 == 0 ? 0 : 1)
Run Code Online (Sandbox Code Playgroud)
在F#中,当if没有else分支时使用语句然后隐式返回unit.如果您的then分支返回的类型不是unit您必须具有显式else分支才能使其正常工作.在你的例子中你可以写:
let myFunc x y = if y = 0 then 1 else x
Run Code Online (Sandbox Code Playgroud)
MSDN - http://msdn.microsoft.com/en-us/library/dd233231.aspx