【问题标题】:F# compiler error "This expression was expected to have type unit but here has type bool." expression in {if else} statementsF# 编译器错误“此表达式应具有类型单元,但此处具有类型 bool。” {if else} 语句中的表达式
【发布时间】:2015-02-28 09:25:55
【问题描述】:

我在 F# 中写过这样的函数:

let TwistBasket (reverse: bool, quarters: int, overTwist: int byref) =
    overTwist <- 50
    WaitForBasketReady()
    waitBasket.Reset()
    let move = 135*quarters - 25 + overTwist
    let speed =
        match reverse with
            | true -> -75y
            | false -> 75y
    let waitHandle = motorBasket.SpeedProfile(speed, 15u, uint32 move, 10u, true)
    Task.Factory.StartNew(fun () ->
        waitHandle.WaitOne()
        if (overTwist <> 0) then
            motorBasket.SpeedProfile(sbyte -speed, 0u, uint32 overTwist, 0u, true).WaitOne()
        waitBasket.Set()

关于这个 if 语句;

    if (overTwist <> 0) then
         motorBasket.SpeedProfile(sbyte -speed, 0u, uint32 overTwist, 0u, true).WaitOne()

我收到错误:This expression was expected to have type unit but here has type bool.

其实motorBasket.SpeedProfile().WaitOne()returns布尔语句。我需要它。

因为我试图在 C# 中转换这个 if else 语句:

        Task.Factory.StartNew(() =>
        {
            waitHandle.WaitOne();
            if (overTwist != 0)
            {
                motorBasket.SpeedProfile((sbyte) -speed, 0, (uint) overTwist, 0, true).WaitOne();
            }
            waitBasket.Set();
        });

如何解决我的错误?

【问题讨论】:

  • 您是否尝试在表达式中添加 |> ignore?
  • 如果我添加 |> 忽略,我仍然调用获取结果吗?因为这对我来说很重要。
  • 你想对结果做什么?在 C# 版本中它只是忽略它。
  • 感谢您的帮助古斯塔沃。但实际上我会再次遇到类似的问题,在接下来的陈述中,Petr 的方法可能会更有用。
  • 不用担心。原则上我会坚持使用 C# 版本,然后一旦完成工作翻译,我可能会重构。你的选择!

标签: f# c#-to-f# unit-type


【解决方案1】:

通过查看 C# 版本,它对结果没有任何作用。所以在 F# 中我会调用 ignore 这将 结果:

if (overTwist <> 0) then
     motorBasket.SpeedProfile(sbyte -speed, 0u, uint32 overTwist, 0u, true).WaitOne() |> ignore

在这些情况下,F# 比 C# 更严格,如果你的 if .. then 没有 else 分支,那么它的结果应该是单位,这很有意义。

您还可以使用(虚拟)布尔值创建一个 else 分支并将其绑定到一个(虚拟)值,但在这种特殊情况下,如果您真的不打算使用该值,那又有什么意义呢?您真正在做的是创建副作用并忽略结果,F# 驱使您在代码中使其更加明确。

【讨论】:

    【解决方案2】:

    在 F# 中,if/else 表达式应该具有相同的类型。如果您使用没有else 分支的if 表达式,那么F# 编译器会隐含地认为else 分支具有unit 类型,因此会出现错误。 您可以更改代码以显式使用 else 分支:

    if (overTwist <> 0) then
        motorBasket.SpeedProfile(sbyte -speed, 0u, uint32 overTwist, 0u, true).WaitOne()
    else
        ... // Put here expression of the same type as if (I assume it's bool)
    

    或者您可以在 Gustavo 提到的 if 分支中使用 ignore 函数。

    【讨论】:

    • 其实单独加一个else分支并不能解决问题。您需要将 if .. then .. else .. 表达式分配给 let-bind 值。如果未使用该值,您可以执行let _ = if .. then .. else .. .. 无论如何,在这种情况下最好将表达式发送到ignore,但是您不需要else ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多