【发布时间】:2015-07-26 18:20:59
【问题描述】:
我将首先介绍一个具体问题(StackOverflow 的人就是这样)。 假设你定义了一个简单的类型
data T a = T a
此类型为Functor、Applicative 和Monad。忽略自动派生,要获得这些实例,您必须编写每个实例,即使 Monad 暗示 Applicative,也暗示 Functor。
不仅如此,我还可以定义一个这样的类
class Wrapper f where
wrap :: a -> f a
unwrap :: f a -> a
这是一个相当强的条件,它肯定暗示Monad,但我不会写
instance Wrapper f => Monad f where
return = wrap
fa >>= f = f $ unwrap fa
因为出于某种原因,这意味着“所有东西都是Monad(每个f),只有当它是Wrapper”,而不是“所有Wrapper 都是Monad”。
同样,您不能定义 Monad a => Applicative a 和 Applicative a => Functor a 实例。
你不能做的另一件事(这可能只是相关的,我真的不知道)是让一个类成为另一个类的超类,并提供子类的默认实现。当然,class Applicative a => Monad a 很好,但在定义Monad 实例之前,我仍然需要定义Applicative 实例。
这不是咆哮。我写了很多,否则这很快就会被标记为“太宽泛”或“不清楚”。问题归结为标题。 我知道(至少我很确定)这有一些理论上的原因,所以我想知道这里到底有什么好处。
作为一个子问题,我想问一下是否有可行的替代方案仍然保留所有(或大部分)这些优势,但允许我写的内容。
补充:
我怀疑其中一个答案可能类似于“如果我的类型是Wrapper,但我不想使用这暗示的Monad 实例怎么办?”。对此我要问,为什么编译器不能选择最具体的一个?如果有instance Monad MyType,肯定比instance Wrapper a => Monad a 更具体。
【问题讨论】:
-
unwrap描述了一种Monad的方法都没有实现的行为;如果不是这种情况,unwrap将允许您从IO a计算中提取a(就像unsafePerformIO所做的那样),这首先会破坏拥有IOmonad 的目的.一个类只能不如其子类强大/富有表现力。 -
当为
Maybe类型定义实例时,Nothing的unwrap的定义是什么? -
@Sibi 简单,Maybe 没有实例。我不认为他声称有。另外,我怀疑 Wrapper 暗示 Monad 没有任何法律(除了免费法律)。
-
@Jubobs 尽管如此,Luka 的实际主张(即任何可以作为
Wrapper的实例并满足一些明显规律的东西也可以以机械方式成为Monad的实例) 是正确的。 -
在github.com/Frege/frege 中可以通过为子类提供实例来一次实现所有超类。这在子类具有超类函数的默认实现的情况下特别有用,这也是受支持的。 OTOH,Frege 仅支持单参数类型类,如 Haskell 2010。
标签: haskell monads typeclass functor applicative