F# compiler error “This expression was expected to have type unit but here has type bool.” expression in {if else} statements

不打扰是莪最后的温柔 提交于 2019-12-10 17:14:29

问题


I have written such a function in 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()

On this if statement ;

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

I get the error: This expression was expected to have type unit but here has type bool.

Actually motorBasket.SpeedProfile().WaitOne()returns boolean statement. I need it.

Because I'm trying to convert this if else statement in C#:

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

How can I fix my error?


回答1:


By looking at the C# version, it does nothing with the result. So in F# I would call ignore which will eat the result:

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

F# is more strict than C# in these cases, if your if .. then has no else branch it result should be unit, which makes perfect sense.

You can also create an else branch with a (dummy) boolean value and let-bind it to a (dummy) value, but in this particular case what's the point if you're really not going to use that value? What you're really doing is creating a side effect and ignoring the result, F# drives you to make it more explicit in your code.




回答2:


In F# if/else expressions should have the same type. If you are using if expression without else branch then F# compiler consider that implicitly else branch has type unit hence the error. You could change your code to explicitly use else branch:

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)

Or you can use ignore function in if branch as Gustavo mentioned.



来源:https://stackoverflow.com/questions/27735519/f-compiler-error-this-expression-was-expected-to-have-type-unit-but-here-has-t

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!