F#编译器错误“这个表达式应该有类型单位,但这里有bool类型。” {if else}语句中的表达式

时间:2015-01-01 23:04:14

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

我在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()返回布尔语句。我需要它。

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

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

如何修复错误?

2 个答案:

答案 0 :(得分:3)

通过查看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#驱使您在代码中使其更明确。

答案 1 :(得分:2)

在F#if/else中,表达式应该具有相同的类型。如果您使用if表达式而没有else分支,那么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函数。