haskell - 哈斯克尔。如何使用 GADT 实现自定义 monad 转换器?
问题描述
我正在尝试通过实现我自己的来了解 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)`
对于 applicative 和 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 推断 kind *
,因为这是最简单的。也许,它本可以使这种多类型的,但没有。
如果您想要另一种,请明确要求:
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
这里使用是否有意义。
推荐阅读
- css - 无论比例如何,如何让图像调整大小并填充表格单元格
- android - 调用 HTTP 请求时,Toast 未显示在登录流程中
- unity3d - 如何在 2019 年 8 月之后发布我的游戏(由 unity 制作)供 google play 使用?
- php - laravel 5.4 雄辩的创建
- c# - C# 属性传递将分配给计算值的属性名称
- android - 是否可以在激活即时应用程序链接的同时隐藏商店中的“立即尝试”按钮?
- push-notification - Web Socket 连接已关闭,状态码为 1006 (SignalR)
- javascript - 如何使用 reactjs 根据用户输入列出所有建议和过滤建议?
- html - 如何更改维恩图中的交叉点颜色?
- vmware - 调整(扩展)vmware vm 磁盘大小