9

標準Monadクラスには欠陥があり、実際に拡張する必要がある、FunctorまたはPointed浮かんでいるという考え。

私は必ずしもそれが正しいことだと主張しているわけではありませんが、誰かがそれをやろうとしていたとします:

import Prelude hiding (Monad(..))

class Functor m => Monad m where
    return :: a -> m a
    join :: m (m a) -> m a
    join = (>>= id)
    (>>=) :: m a -> (a -> m b) -> m b
    a >>= t = join (fmap t a)
    (>>) :: m a -> m b -> m b
    a >> b = a >>= const b

これまでのところは問題ありませんが、do 表記法を使用しようとすると、次のようになります。

whileM :: Monad m => m Bool -> m ()
whileM iteration = do
    done <- iteration
    if done
        then return ()
        else whileM iteration

コンパイラは不平を言います:

Could not deduce (base:GHC.Base.Monad m) from the context (Monad m)

質問:

do 表記は に対してのみ機能しbase:GHC.Base.Monadますか? Monad代替クラスで動作させる方法はありますか?

追加のコンテキスト:

私が本当にやりたいことはbase:Control.Arrow.Arrow、「一般化された」Arrowクラスに置き換えることです。

{-# LANGUAGE TypeFamilies #-}

class Category a => Arrow a where
    type Pair a :: * -> * -> *
    arr :: (b -> c) -> a b c
    first :: a b c -> a (Pair a b d) (Pair a c d)
    second :: a b c -> a (Pair a d b) (Pair a d c)
    (***) :: a b c -> a b' c' -> a (Pair a b b') (Pair a c c')
    (&&&) :: a b c -> a b c' -> a b (Pair a c c')

そしてArrow、クラスで の proc 表記を使用Arrowしますが、上記の do 表記と の例のように失敗しますMonad

現在のクラスのような型コンストラクターではなく、主Eitherにペア型コンストラクターとして使用します。これにより、私のおもちゃの RTS ゲーム ( ) のコードをよりきれいにすることができるかもしれません。(,)Arrowcabal install DefendTheKind

4

1 に答える 1

20

とを含む完全な再バインド可能な構文には、 NoImplicitPrelude 拡張を使用する必要がありdoますproc。その場合、とりわけ次のものが得られます。

「Do」表記は、(>>=)、(>>)、および失敗の関数を使用して変換され、スコープ内にあります (Prelude バージョンではありません)。リスト内包表記、mdo (セクション 7.3.6、「再帰的な do 記法」)、および並列配列内包表記は影響を受けません。

否定、等価、リテラル値などの処理を調整することもできます。コードを難読化する優れた方法です。

dops --構文を再バインドするつもりなら、 sigfpe が「パラメータ化されたモナド」と呼ぶものはとても楽しいものです。Control.Monad.Indexedcategory-extrasの下でも同じ考え方が利用できます。はい、型シグネチャが大きく異なるにもかかわらず、それらは再バインド可能な構文で動作します!

于 2010-05-13T23:56:34.720 に答える