我目前正在阅读Kan Extensions for Program Optimisation,在论文的第一页,作者定义了给定M的单子,下面的单子
type C a = ∀z . (a → M z ) → M z
instance Monad C where
return a = λc → c a
m >>= k = λc → m (λa → k a c)
所以我尝试使用M=Maybe来处理它,因此编写了以下代码
type C a = forall z . (a -> Maybe z) -> Maybe z
instance Monad C where
return a = \c -> c a
m >>= k = \c -> m $ \a -> k a c
但它不会编译并输出
主。hs:22:10:·类型同义词“C”应该有1个参数,但没有给出任何参数
我无法解释。这是怎么回事?* (我做了一些范畴理论,但我刚刚开始学习Haskell)。
2条答案
按热度按时间wyyhbhjk1#
正如注解中所指出的,您需要一个
newtype
。type
别名只是为了方便程序员,并不是不同的实体,而你想要实现一个类型类,所以你需要一个不同的实体。你可以这样写newtype
。尽管如此,我还是建议包括一个访问器,因为我们稍后将需要它来进行封送处理。
(If如果你在家里沿着,你需要
{-# LANGUAGE RankNTypes #-}
来实现这个forall
语法。这是一个编译器扩展,使特定的爱好者类型)需要明确的是,我们不会为
forall z. (a -> Maybe z) -> Maybe z
编写Monad
示例。那种人不属于我们我们将为C a
编写一个Monad
示例,C a
是我们刚刚创建的一个新类型,它 * 恰好 * 以一种很好的方式与forall z. (a -> Maybe z) -> Maybe z
同构。现在
Monad
依赖于Functor
和Applicative
,所以我们从这里开始。Functor
是derive-able,所以我们可以只写deriving (Functor)
,但知道如何写出这些也是很好的实践。现在是
Applicative
根据相应的Monad
示例来实现Applicative
是非常常见的,所以我们在这里就这样做。(Note:
ap
来自Control.Monad
模块,因此您也需要导入该模块)只要您编写
Monad
示例时不调用pure
或<*>
,这种方法就始终有效。现在是
Monad
。它与您所写的几乎完全一样,除了一些C
和unC
封送处理以使类型检查器满意。最后,请注意,我们在这里从未实际使用过
Maybe
或其任何属性。我们不仅不关心M
是什么,我们甚至不需要它是Functor
。所以我们也可以用它来参数化。现在,
C Maybe
与您刚刚使用的C
类型相同,但我们可以将* -> *
类型的任何东西替换为m
。* 任何东西 *,不仅仅是Functor
s。狂野一点cwxwcias2#
不能使用部分应用于示例的类型别名。在这种情况下,通常使用
newtype
来创建一个新类型,但本质上只是它 Package 的类型:然后将示例定义为:
因此,它在
C
构造函数中执行了一些 Package 和解 Package 操作,但这些操作本质上是无操作的。