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

yai*_*chu 9 monads haskell 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
Run Code Online (Sandbox Code Playgroud)

到目前为止一切顺利,但在尝试使用do-notation时:

whileM :: Monad m => m Bool -> m ()
whileM iteration = do
    done <- iteration
    if done
        then return ()
        else whileM iteration
Run Code Online (Sandbox Code Playgroud)

编译器抱怨:

Could not deduce (base:GHC.Base.Monad m) from the context (Monad m)
Run Code Online (Sandbox Code Playgroud)

题:

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')
Run Code Online (Sandbox Code Playgroud)

然后在Arrow我的Arrow类中使用's proc-notation ,但是在上面的do-notation例子中失败了Monad.

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

C. *_*ann 20

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

"Do"符号使用任何函数(>> =),(>>)进行转换,并且失败,在范围内(不是Prelude版本).列表推导,mdo(第7.3.6节"递归标记")和并行数组推导不受影响.

您还可以调整一些否定,相等,字面值和诸如此类的处理.混淆代码的好方法!

ps - 如果要重新绑定do语法,sigfpe称之为"参数化monad"非常有趣.同样的想法是在提供category-extrasControl.Monad.Indexed.是的,他们确实使用可重新绑定的语法,尽管类型签名截然不同!

  • @yairchu:我想这至少部分是由于箭头不经常使用而且`proc`语法本身是一个更新的补充.像GHC团队一样英勇,他们不能只是挥动魔杖来实现每一个想到的功能...... (3认同)
  • 太好了,谢谢!:)而且,arg!:(太糟糕,对于'箭头` - "不像其他构造,这些函数的类型必须非常紧密地匹配Prelude类型",我想知道为什么是.. (2认同)