2017-05-16 3 views
6

私はこのストレートMaybeモナドを実装しようとしました。したがって、基本的には、中間ステップの1つがNothingの場合、式全体がNothingと評価されます。F#計算式がコンバインと呼ばれるとき

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 
    } 

私はfoobarがしかしCombineが呼び出されなかった、Just "foo" >>= fun foo -> Combine(Just 1, Nothing)に変換することが期待されます。

答えて

7

これは、計算式が書き込まれるとは思われません。

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

:あなたが望むたびに、あなたの例では、私はreturn!を追加し、式の左側に(!リターン、!、歩留まりを返すか、降伏)いくつかのキーワードを追加する必要がある「結果をもたらします」しかし、その後、あなたは、ビルダーにその定義を追加する必要があります。

member this.Delay(x) = x() 

member this.ReturnFrom (expr) = expr 

コンパイラはあなたのケースで、私はあなたが何かを探していると思いますが、遅延メソッドを追加するように求めます

ほとんどが、今はCombineあなたが定義したが、両方の引数の同じタイプを使用していないので、あなたはそれを修正するか、単に戻り値の型に型注釈を追加することができますいずれかの可能性が最も高い値の制限を、持っている:

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

、今あなたが得る:

Bind called 
Combine called 
印刷

と::

val foobar : Maybe<int> = Nothing 

を使用すると、CEのすべての詳細を理解したい場合は、この素晴らしい記事を見て

+4

この非常に良いシリーズの記事をフォローアップしてください:https://fsharpforfunandprofit.com/series/computation-expressions.html – rmunn

関連する問題