我目前正在阅读Kan Extensions for Program Optimization,在论文的第一页中,作者定义了给定 M a monad 的以下 monad
\ntype C a = \xe2\x88\x80z . (a \xe2\x86\x92 M z ) \xe2\x86\x92 M z\ninstance Monad C where\n return a = \xce\xbbc \xe2\x86\x92 c a\n m >>= k = \xce\xbbc \xe2\x86\x92 m (\xce\xbba \xe2\x86\x92 k a c)\nRun Code Online (Sandbox Code Playgroud)\n所以我尝试使用 M=Maybe 来玩一下它,因此编写了以下代码
\ntype C a = forall z . (a -> Maybe z) -> Maybe z\n\ninstance Monad C where\n return a = \\c -> c a\n m >>= k = \\c -> m $ \\a -> k a c\nRun Code Online (Sandbox Code Playgroud)\n但它不编译并输出
\n\n\nMain.hs:22:10: 错误:\n\xe2\x80\xa2 类型同义词 \xe2\x80\x98C\xe2\x80\x99 应该有 1 个参数,但没有给出任何参数
\n
我无法解释。这里出了什么问题?\n (我已经完成了一些范畴论,但我刚刚开始学习 Haskell)。
\n正如评论中指出的,您需要一个newtype. type别名只是程序员的便利,并不是不同的实体,并且您想要实现一个类型类,因此您需要一个不同的实体。newtype你可以这样写。
newtype C a = C (forall z . (a -> Maybe z) -> Maybe z)
Run Code Online (Sandbox Code Playgroud)
不过我建议包括一个访问器,因为我们稍后需要它来进行编组。
newtype C a = C { unC :: forall z . (a -> Maybe z) -> Maybe z }
Run Code Online (Sandbox Code Playgroud)
(如果您在家中遵循,则需要{-# LANGUAGE RankNTypes #-}能够执行此forall语法。它是一个编译器扩展,可以启用该特定的更高级类型)
需要明确的是,我们不会Monad为forall z. (a -> Maybe z) -> Maybe z. 这种类型不属于我们。我们将为 编写一个Monad实例C a,这是我们刚刚创建的一个新类型,它恰好以一种很好的方式同构forall z. (a -> Maybe z) -> Maybe z。
现在Monad取决于Functor和Applicative,所以我们将从这里开始。
Functor是可导出的,所以我们可以只写deriving (Functor),但知道如何写出这些也是一个很好的做法。
instance Functor C where
fmap f (C a) = C $ \k -> a (k . f)
Run Code Online (Sandbox Code Playgroud)
现在Applicative。Applicative根据相应的实例来实现是很常见的Monad,所以我们将在这里这样做。
instance Applicative C where
pure = return
(<*>) = ap
Run Code Online (Sandbox Code Playgroud)
(注意:ap来自Control.Monad模块,因此您也需要导入它)
只要您编写Monad实例而不调用pure或,这总是有效的<*>。
现在Monad。它几乎与您所写的完全一样,除了一些内容C和unC编组以使类型检查器满意之外。
instance Monad C where
return a = C (\c -> c a)
m >>= k = C (\c -> unC m $ \a -> unC (k a) c)
Run Code Online (Sandbox Code Playgroud)
最后,请注意,我们Maybe在这里从未实际使用过或其任何属性。我们不仅不关心那M是什么,甚至不需要它是一个Functor. 所以我们也可以通过它来参数化。
{-# LANGUAGE RankNTypes #-}
import Control.Monad
newtype C m a = C { unC :: forall z . (a -> m z) -> m z }
instance Functor (C m) where
fmap f (C a) = C $ \k -> a (k . f)
instance Applicative (C m) where
pure = return
(<*>) = ap
instance Monad (C m) where
return a = C (\c -> c a)
m >>= k = C (\c -> unC m $ \a -> unC (k a) c)
Run Code Online (Sandbox Code Playgroud)
Now与您刚刚使用的类型C Maybe相同,但我们可以用任何类型来代替. 任何东西,不仅仅是s。去野外。C* -> *mFunctor
| 归档时间: |
|
| 查看次数: |
108 次 |
| 最近记录: |