2017-05-16 33 views
6

Próbowałem zaimplementować tę prostą monadę Maybe. Zasadniczo całe wyrażenie ma wartość Nothing, jeśli jednym ze środkowych kroków jest Nothing.Wyrażenie obliczeń F #, gdy jest to połączenie o nazwie

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 
    } 

Spodziewałem foobar być przetłumaczone na język Just "foo" >>= fun foo -> Combine(Just 1, Nothing) jednak Combine nie został powołany.

Odpowiedz

7

To nie jest sposób, w jaki należy zapisać wyrażenie obliczeniowe. Za każdym razem gdy chcesz „uzyskując wynik” trzeba dodać jakieś słowa kluczowego (! Powrotną, powrót !, wydajność lub wydajność) po lewej stronie wyrażenia, w przykładzie chciałbym dodać return!:

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

ale wtedy trzeba dodać swoją definicję do konstruktora:

member this.ReturnFrom (expr) = expr 

następnie kompilator poprosi Cię dodać metodę zwłoki, w twoim przypadku myślę, że szukasz czegoś podobnego:

member this.Delay(x) = x() 

Prawie tam, teraz masz ograniczenie wartości, najprawdopodobniej dlatego, że Combine zdefiniowano nie używać tego samego typu na obu argumentów, można go naprawić lub po prostu dodać typ adnotacji w Zwraca typ:

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

to wszystko, teraz masz:

Bind called 
Combine called 

drukowane oraz:

val foobar : Maybe<int> = Nothing 

Jeśli chcesz zrozumieć wszystkie szczegóły CE rzucić okiem na ten miły artykułu: https://www.microsoft.com/en-us/research/publication/the-f-computation-expression-zoo/

+4

Następnie przejdź do tego artykułu z bardzo ładną serią artykułów: https://fsharpforfunandprofit.com/series/computation-expressions.html – rmunn