问题描述
我正在尝试通过实现自己的方法来学习monad变压器。编码
如果我使用newType DummyT m x y z = DummyT { runDummyT :: m (Dummy x y z) }
则编译
但如果我使用GADT,则不会。但是我需要使用GADT,但似乎更多
难。我收到此错误:
Expecting one more argument to ‘m’
Expected a type,but ‘m’ has kind ‘* -> *’
In the first argument of ‘DummyT’,namely ‘m’
In the first argument of ‘Functor’,namely ‘(DummyT m x y)`
对于应用实例和monad实例,我得到相同的错误。 为什么会出现此错误?任何帮助表示赞赏。
我的单子:
instance Monad (Dummy x y) where
return = Return
(>>=) = Bind
data Dummy x y z where
Return :: z -> Dummy x y z
Bind :: Dummy x y z -> (z -> Dummy x y q) -> Dummy x y q
变压器尝试:
instance Monad m => Functor (DummyT m x y) where
fmap = liftM
instance Monad m => applicative (DummyT m x y) where
pure = return
(<*>) = ap
instance Monad m => Monad (DummyT m x y) where
return = Return
(>>=) = Bind
data DummyT m x y z where
Return :: z -> DummyT m x y z
Bind :: DummyT m x y z -> (z -> DummyT m x y q) -> DummyT m x y q
解决方法
在
newType DummyT m x y z = DummyT { runDummyT :: m (Dummy x y z) }
m
的种类显然是* -> *
,因为m
被应用于一种类型。
在
data DummyT m x y z where
Return :: z -> DummyT m x y z
Bind :: DummyT m x y z -> (z -> DummyT m x y q) -> DummyT m x y q
m
未使用,因此GHC推断类型为*
,因为这是最简单的。也许可以使这种多面性,但是没有。
如果您想要另一种,请明确要求它:
data DummyT (m :: * -> *) x y z where
Return :: z -> DummyT m x y z
Bind :: DummyT m x y z -> (z -> DummyT m x y q) -> DummyT m x y q
不过,我想知道,如果不使用m
,是否有意义?