1

このように「バインド」関数を定義すると、次のようになります。

(>>=) :: M a -> (a -> M' b) -> M' b

結果を新しいモナドタイプにしたい場合、または同じモナドを使用する必要があるが、以前と同じモナドボックスにbを使用する必要がある場合、この定義は役に立ちますか?

4

4 に答える 4

7

コメントで述べたように、そのような操作は一般的なモナド(例えばM = IOM' = Maybe)に対して安全に定義できるとは思いません。

ただし、Mが安全にM'に変換できる場合、このバインドは次のように定義できます。

convert :: M1 a -> M2 a
...

(>>=*) :: M1 a -> (a -> M2 b) -> M2 b
x >>=* f = convert x >>= f

そして逆に、

convert x = x >>=* return

このような安全な変換方法のいくつかは、maybeToList(多分→[])、listToMaybe([]→多分)、stToIO(ST RealWorld→IO)、...convertどのモナドにも一般的な方法がないことに注意してください。

于 2010-07-16T19:26:47.573 に答える
1

その定義は役に立たないだけでなく、コードの将来の読者を深刻に混乱させるでしょう。なぜなら、それはそれに対する使用のすべての期待を破るからです。

たとえば、MとM'の両方がモナドであると想定されていますか?もしそうなら、それらはどのように定義されていますか?覚えておいてください:の定義>>=はモナドの定義の一部であり、他のモナドを使用する関数を定義するためにどこでも使用されます-それ以外のすべての関数returnfailそれ自体。

また、使用するMとM'を選択することはできますか、それともコンピューターを使用しますか?もしそうなら、どのように選択しますか?それは任意の2つのモナドインスタンスで機能しますか、それとも必要なモナドのサブセットがありますか?またはMの選択がM'の選択を決定しますか?

あなたが書いたような関数を作ることは可能ですが、それは確かにそれよりもはるかに複雑であり、あなたの関数を服>>=に詰め込もうとすると、誤解を招き、残酷で、潜在的に悲惨なことになります。>>=

于 2010-07-16T22:23:40.010 に答える
1

これは複雑な作業になる可能性がありますが、状況によっては実行可能です。基本的に、それらが内部で見ることができるモナド(Maybeまたはあなたが書いたモナドなど)である場合、そのような操作を定義できます。

Monad(GHCで)時々非常に便利なことの1つは、クラスを独自のクラスに置き換えることです。定義した場合でも、表記return, >>=, failを使用できます。doこれがあなたが望むもののようなかもしれない例です:

class Compose s t where
  type Comp s t

class Monad m where
  return :: a -> m s a
  fail  :: String -> m a
  (>>=) :: (Compose s t) => m s a -> (a -> m t b) -> m (Comp s t) b
  (>>)  :: (Compose s t) => m s a -> m t b -> m (Comp s t) b
  m >> m' = m >>= \_ -> m'

次に、定義したインスタンスに基づいて、バインド演算子を使用してシーケンスできるタイプを制御できComposeます。当然、必要になることがよくありますがComp s s = s、これを使用して、あらゆる種類のクレイジーなものを定義することもできます。

たとえば、モナドにいくつかの操作があり、他の操作を絶対に実行できない場合があります。それを静的に強制したいですか?空のデータ型を定義し、data Terminalのインスタンスを提供しませんCompose Terminal t

Maybeこのアプローチは、(たとえば)からに移調するのには適していませんIOが、実行していることに関するタイプレベルのデータを運ぶために使用できます。

モナドを本当に変更したい場合は、上記のクラス定義を次のように変更できます。

class Compose m n where
  type Comp m n
  (>>=*) :: m a -> (a -> n b) -> (Compose m n) b

class Monad m where
  return :: a -> m a
  fail :: String -> m a
  (>>=) :: Compose m n => m a -> (a -> n b) -> (Compose m n) b
  m >>= f = m >>=* f
  (>>) :: Compose m n => m a -> (n b) -> (Compose m n) b
  m >> n = m >>=* \_ -> n

私は前者のスタイルを有用な目的に使用しましたが、この後者のアイデアは特定の状況でも役立つ可能性があると思います。

于 2010-07-17T04:16:04.537 に答える
0

Olegのこのサンプルをご覧になることをお勧めします:http://okmij.org/ftp/Computation/monads.html#param-monad

于 2010-07-16T23:36:51.810 に答える