3

Monteプログラミング言語とその祖先のEには、「エジェクター」と呼ばれるシングルショットで区切られた継続の構文があります。これは、構文境界内で一度だけ使用できる継続です。たとえば、呼び出されないイジェクターは次のとおりです。

escape ej { 42 }

そして、次の名前のイジェクター:

escape ej { ej(42); "After 10,000 years, I'm free!" }

どちらも に評価され42ます。イジェクターが呼び出されるケースにアクションを追加することもできます。

escape ej { ej(2) } catch result { result + 4 }

それがこの構文のすべてです。これがどのようにMaybeまたはを模倣するかを想像するのは難しくありませんEitherHaskell Wiki on Maybeの例を慣用的なモンテに書き写します。

def f(x, ej):
    return if (x == 0) { ej() } else { x }

def g(x, ej):
    return if (x == 100) { ej() } else { x }

def h(x, ej):
    return g(f(x, ej), ej)

# Monte permits Unicode identifiers but not for free.
def ::"h´"(x, ej):
    def n := f(x, ej)
    return g(n, ej)

( を渡す負担をどのように負担しなければならないかに注意してくださいej。Monte には、do 表記の「プログラム可能なセミコロン」がありません。)

しませんがEither、ほとんど同じです。句を追加する機能catchにより、必要なタイプの識別が提供されます。区切られた継続は構成することがよく知られているため、複雑なツールを構築することが可能です:

def trying(f, g, ej):
    return escape innerEj { f(innerEj) } catch _ { g(ej) }

これらの種類のガジェットは、Monte で手書きのパーサー コンビネーターなどを構築するために使用されます。したがって、すべてのモナドの母で、ダン・ピポニはCont、ある意味で、Monad他の多くのモナドをMonad構築できる非常に原始的なものであると説明しています。モンテでもこれを試みることができます。オブジェクトベースの言語でモナドをエンコードするために Moggi のスタイルを使用しましょう。

object identity:
    to unit(x):
        return x

    # "bind" is a Monte keyword; we may still use it, but not for free.
    # NB this is `x >>= f` in Haskell.
    to "bind"(x, f):
        return f(x)

そして、バインディング ヘルパーiをエンコードして、それがどのように見えるかを理解しましょう。

def i(m, x, ej):
    return m."bind"(x, ej)

...これは役に立ちません。これは良い構文のようには見えません。

# Haskell: runIdentity $ do { x <- return 32; return $ x // 4 }
escape ej { i(identity, i(identity, identity.unit(32), fn x { identity.unit(x // 4) }), ej) }

未来にはクールなロボットが登場するはずだったが、これはそうではなかった。ただし、別の問題があります。Monad別の伝統的な, をエンコードしましょうList:

object list:
    to unit(x) { return [x] }

    to "bind"(action, f):
        var rv := []
        for x in (action) { rv += f(x) }
        return rv

そして、伝統的なデカルト積をやってみましょう。まず、直接計算してみましょう。継続を渡す代わりに、リストモナドを使って直接バインドします:

▲&gt; i(list, [1, 2, 3], fn x { i(list, [4, 5, 6], fn y { [x * y] }) })
Result: [4, 5, 6, 8, 10, 12, 12, 15, 18]

そして今、エジェクタを使用して:

▲&gt; escape ej { i(list, i(list, [1, 2, 3], fn x { i(list, [4, 5, 6], fn y { [x * y] }) }), ej) }
Result: 4

そう!それはかなり興味深いです。完全なリストモナド計算が実行されていますが、イジェクタはリストの最初の項目しか認識しません。エジェクターは構成可能であるため、多くの中間結果を計算しないというより良い仕事をする、より洗練された論理モナドを構築する方法があると思います。

私の質問は次のとおりです。慣用的なモンテに変換するMaybeEither、エジェクタ構文がエレガントに適用されることがはっきりとわかります。このような興味深い単発動作を持つモナドが他にあるでしょうか? Haskell に限定されていると感じないでください。Monte は型付けされていないので、型付けが難しいモナドを理由にあなたを敬遠する人はいません!

4

0 に答える 0