1

Try F# の Web サイトでは、計算式の例が示されています。

type Age =
| PossiblyAlive of int
| NotAlive

type AgeBuilder() =
    member this.Bind(x, f) =
        match x with
        | PossiblyAlive(x) when x >= 0 && x <= 120 -> f(x)
        | _ -> NotAlive
    member this.Delay(f) = f()
    member this.Return(x) = PossiblyAlive x

let age = new AgeBuilder()

let willBeThere (a:int) (y:int) =
  age { 
    let! current = PossiblyAlive a
    let! future = PossiblyAlive (current + y)

    return future
  }

これは、Haskell にある標準の Maybe モナドに少し似ています。

ただし、真の Haskell 形式では、次の 2 行に return を使用したいと思います。

let! current = PossiblyAlive a
let! future = PossiblyAlive (current + y)

することが:

let! current = return a
let! future = return (current + y)

しかし、それは機能しません。私が得る最も近いものは次のとおりです。

let! current = age.Return a
let! future = age.Return (current + y)

しかし、これは汚れているようです。return計算ビルダー関数を明示的に使用せず に使用する方法はありますか?

4

2 に答える 2

3

ネストされた式を作成できます。

let! current = age { return a }
let! future = age { return (current + y) }

let代わりに使用することもできますが:

let current = a
let future = current + y

このビルダーはモナドの法則に違反していることに注意してください。

return 150 >>= returnと同じではありませんreturn 150

于 2014-07-08T11:55:24.757 に答える
0

age { return <expr> }この問題をより詳細に調べたところ、リーが回答で示した構文を使用するための合理的な代替手段を見つけたと思います。

この構文の私の主な弱点は、私たちがすでにageモナドにいるということです。したがってreturn、本体内のステートメントは自動的に に解決されるはずage.Returnです。ただし、回避策は非常に簡単であるため、これを修正することはおそらく F# チームにとって優先度が非常に低いでしょう。

私の代替手段はBind、値を取り、それを持ち上げる関数でメソッドをオーバーロードすることです。次に、この持ち上げられた値を他のBind関数に送信します。

type Age =
| PossiblyAlive of int
| NotAlive

type AgeBuilder() =
    let reasonableAge (x:int) = x >= 0 && x <= 120

    member __.Return x = 
        if reasonableAge x then PossiblyAlive x else NotAlive

    member __.Bind(x:Age, f) =
        match x with
        | PossiblyAlive x when reasonableAge x -> f x
        | _ -> NotAlive

    member this.Bind(x:int, f) =
        this.Bind(this.Return(x), f)

let age = new AgeBuilder()

let willBeThere (a:int) (y:int) =
    age { 
        let! current = a
        let! future = (current + y)
        return future
    }
于 2014-08-01T23:05:01.553 に答える