If / Then中的F#推断类型

时间:2013-05-10 17:20:35

标签: f# type-inference unit-type

如果我有以下功能:

let myFunc x y =
  if y = 0 then 1
  x

我收到错误:

Program.fs(58,17): error FS0001: This expression was expected to have type
    unit    
but here has type
    int    

为什么编译器期望'unit'而不是int?

2 个答案:

答案 0 :(得分:9)

值得补充的是,这不仅仅是if的属性。 F#是一种基于表达式的语言,意味着几乎每一段代码(除了类型声明和一些例外)都是一个表达式,它评估一些结果。事实上,F#不会调用if if 语句,而是调用if 表达式

这意味着您可以在意外的地方使用if。例如,这可能很有用:

x/2 + (if x%2=0 then 0 else 1) 

正如Garry已经解释的那样,如果省略else,那么表达式仍然需要返回一些东西 - 如果结果是int,那么它就没有意义(哪个数字)如果编译器选择?),那么它要求结果是unit类型,这是一种表示“无结果”的特殊类型。

unit类型也是所有命令函数(例如printf)或所有不逻辑返回任何值(赋值或例如循环)的表达式的结果。这意味着如果你写:

if x > 0 then printfn "Big!"

...然后表达式是良好类型的,因为printfn "Big!"具有返回类型unit,并且隐式添加的else分支也返回unit。您可以直接手动创建类型unit的值(类型只有一个值),因此上面实际上对应于:

if x > 0 then printfn "Big!" else ()

从C#的角度来看,将if .. then .. else作为条件运算符更有意义:

x/2 + (x%2 == 0 ? 0 : 1)

答案 1 :(得分:7)

在F#中,当没有if分支时使用else语句时,它会隐式返回unit。如果您的then分支返回unit以外的类型,则必须具有明确的else分支才能使其正常工作。在你的例子中,你可以写:

let myFunc x y = if y = 0 then 1 else x

MSDN - http://msdn.microsoft.com/en-us/library/dd233231.aspx