简体   繁体   中英

F# computation expression when is Combine called

I tried to implement this straight forward Maybe monad. So basically the whole expression evaluates to Nothing if one of the middle step is Nothing .

type Maybe<'a> =
    | Just of 'a
    | Nothing
type MaybeBuilder () =
    member this.Combine ((first, second) : Maybe<'a> * Maybe<'b>) : Maybe<'b> =
        printfn "Combine called"
        match first with
        | Nothing -> Nothing
        | _ ->
            match second with
            | Nothing -> Nothing
            | _ as a -> a
     member this.Zero () = Just ()
     member this.Bind((m, f) : Maybe<'a> * ('a -> Maybe<'b>)) =
        printfn "Bind called"
        match m with
        | Nothing -> Nothing
        | Just a -> f a
let MaybeMonad = MaybeBuilder()
let foobar =
    MaybeMonad {
        let! foo = Just "foo"
        Just 1
        Nothing
    }

I expected foobar be translated into Just "foo" >>= fun foo -> Combine(Just 1, Nothing) , however Combine wasn't called.

That's not the way the computation expression is expected to be written. Each time you want 'yield a result' you need to add some keyword (return, return!, yield or yield!) on the left side of the expression, in your example I would add a return! :

let foobar =
    MaybeMonad {
        let! foo = Just "foo"
        return! Just 1
        return! Nothing
    }

But then you need to add its definition to the builder:

member this.ReturnFrom (expr) = expr

then the compiler will ask you to add a Delay method, in your case I think you're looking for something like:

member this.Delay(x) = x()

Almost there, now you have a value restriction, most likely because the Combine you defined doesn't use the same type on both arguments, you can either fix it or just add a type annotation in the return type:

let foobar : Maybe<int> =
    MaybeMonad {
        let! foo = Just "foo"
        return! Just 1
        return! Nothing
    }

That's it, now you get:

Bind called
Combine called

printed and:

val foobar : Maybe<int> = Nothing

If you want to understand all the details of CEs have a look at this nice article: https://www.microsoft.com/en-us/research/publication/the-f-computation-expression-zoo/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM