Evaluating F # Expression When Calling Combine

I tried to implement this straightforward monad Maybe. Thus, in general, the whole expression is evaluated as Nothingif one of the middle steps 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 to foobarbe transferred to Just "foo" >>= fun foo -> Combine(Just 1, Nothing), but was Combinenot called.

+6
source share
1 answer

This is not what the calculation expression is expected to be written to. Every time you want to "give 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 return!:

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

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

member this.ReturnFrom (expr) = expr

Delay, , - :

member this.Delay(x) = x()

, , , Combine, , , , :/p >

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

, :

Bind called
Combine called

val foobar : Maybe<int> = Nothing

CE, : https://www.microsoft.com/en-us/research/publication/the-f-computation-expression-zoo/

+7

Source: https://habr.com/ru/post/1017280/


All Articles