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-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
我的课程中使用 's proc-notation Arrow
,但这就像上面的 do-notation 示例和Monad
.
我将主要Either
用作我的对类型构造函数,而不是(,)
像当前Arrow
类那样的类型构造函数。这可能会使我的玩具 RTS 游戏 ( cabal install DefendTheKind
) 的代码更漂亮。