【问题标题】:F# inferred types in If/ThenIf/Then 中的 F# 推断类型
【发布时间】:2013-05-05 10:56:32
【问题描述】:

如果我有以下功能:

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 ?

【问题讨论】:

  • 您将其标记为 if-statement 的事实说明了 -- 在 F# 中,if 是一个表达式。 :-]
  • 感谢狙击。
  • @ildjarn 虽然 F# 可能会将 if 视为 表达式,但其他语言不会。仅仅为了 F# 对if 的理解而有一个标签可能会给其他人带来很大的困惑......

标签: f# type-inference unit-type


【解决方案1】:

在 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

【讨论】:

    【解决方案2】:

    值得补充的是,这不仅仅是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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-29
      • 2012-07-17
      • 1970-01-01
      相关资源
      最近更新 更多