是“特定于”基础:GHC.Base.Monad“吗?

时间:2010-05-13 23:09:07

标签: haskell monads ghc

标准Monad类存在缺陷并且实际应该扩展FunctorPointed的想法正在浮动。

我不一定声称这是正确的做法,但假设有人试图这样做:

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-notation时:

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-notation是否仅适用于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类中使用Arrow的proc-notation,但是在上面的do-notation和Monad示例中失败了。

我主要使用Either作为我的对类型构造函数,而不是(,)类型构造函数,与当前Arrow类一样。这可能会让我的玩具RTS游戏(cabal install DefendTheKind)的代码变得更漂亮。

1 个答案:

答案 0 :(得分:20)

您需要使用NoImplicitPrelude extension获取完全可重新绑定的语法,包括doproc。在这种情况下,您可以获得以下内容:

  

“Do”符号使用任何函数(&gt;&gt; =),(&gt;&gt;)和失败进行翻译,都在范围内(不是Prelude版本)。列表推导,mdo(第7.3.6节“递归标记”)和并行数组推导不受影响。

你也可以调整一些否定,平等,文字值和诸如此类的处理。混淆代码的好方法!

P.S。 - 如果您要重新绑定do语法,what sigfpe calls "parameterized monads"非常有趣。 category-extras下的{{1}}提供了同样的想法。是的,他们确实使用可重新绑定的语法,尽管类型签名截然不同!