【问题标题】:"This expression was expected to have type unit" but I want it to be boolean“这个表达式应该有单位类型”,但我希望它是布尔值
【发布时间】:2014-03-15 18:44:06
【问题描述】:

我正在尝试创建一个将元组与元组数组的值进行比较的函数。我需要这个来返回一个布尔值,但 VS2013 一直告诉我: "这个表达式应该有'unit'类型,但有'bool'类型"

let compare (i,j,a,(x : (int*int*int) array)) =
    for q in 0 .. x.GetLength(0) do  
        match (i,j,a,x) with
        | (i,j,a,x) when (i,j,a) = x.[q] -> true
        |  _ -> false

也尝试将值作为两个参数给出,但它也不起作用:

let compare (i,j,a) (x : (int*int*int) array) =
    for q in 0 .. x.GetLength(0) do  
        match (i,j,a) with
        | x.[q] -> true
        |  _ -> false

任何帮助将不胜感激!

【问题讨论】:

    标签: types f# tuples unit-type


    【解决方案1】:

    稍微扩展一下 Chris 的回答,您的代码不起作用的主要原因是 F# 是一种 基于表达式的 语言,并且没有命令式控制流您可能会期待这里(如果您将表达式的主体错误地解读为 return 关键字)。

    由于 F# 是基于表达式的,因此所有内容都是计算结果为值的表达式。因此,true 是一个计算结果为真(布尔值)的表达式。您示例中的模式匹配:

    match (i,j,a,x) with
    | (i,j,a,x) when (i,j,a) = x.[q] -> true
    |  _ -> false
    

    ... 也是一个表达式,根据变量的值计算为truefalse(布尔值)。在这种情况下,条件会更简单:

    if (i,j,a,x) = x.[q] then true else false
    

    ...或者您可以只写条件(i,j,a,x) = x.[q],这意味着完全相同的事情。现在,for 循环很棘手,因为它会多次评估主体,因此它可能会获得多个返回值。出于这个原因,F# 有一个特殊的类型 unit(想想 C# 中的 void),它表示一个不携带任何信息的值。所以,for 循环期望 unit-returning body 像:

    for i in 1 .. 10 do 
      printfn "Foo"
    

    您可以检查printfn "Foo" 是否实际返回单位值,例如:

    for i in 1 .. 10 do 
      let nothing = printfn "Foo"
      nothing
    

    如果您将鼠标指针放在nothing 上,您会看到它的类型为unit

    因此,如果您想在中间中断迭代(因为它不能在 F# 中完成),for 循环不是一个好方法。正如 Chris 和 Søren 已经提到的,您可以使用 Array 模块中的函数来轻松实现逻辑。或者,您必须使用递归或可变变量来编写它 - 但 Array 模块在这里工作得很好。

    【讨论】:

    • 扩展,“一点点” :) - 感谢 Tomas,我认为这是从 OP 的问题到单行实现的一大飞跃,需要大量解释
    • 非常感谢!我只是在学习 F#,它非常有趣。喜欢你的接近!
    【解决方案2】:

    又短又甜:

    let compare triple x = Array.exists ((=) triple) x
    

    无需解压元组(i, j, x)

    符号(=) 将相等比较运算符转换为两个柯里化参数的函数。当我们将(=)部分应用到triple时,也就是我们写的时候

    (=) triple
    

    我们得到一个接受一个参数的函数,并将该参数与triple 进行比较,返回真或假。

    【讨论】:

    • let compare triple x = Array.exists ((=) triple) x
    • let compare triple = Array.exists ((=) triple)
    • 工作顺利!谢谢!
    【解决方案3】:

    问题是for 循环期望其中的表达式计算为unit。您将需要一种不同的方法,例如使用Array.exists

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-19
      相关资源
      最近更新 更多