为什么没有 monad 实例Control.Applicative.Const
?以下定义是正确的,还是违反了单子定律?
instance Monoid a => Monad (Const a) where
return _ = Const mempty
(Const x) >>= _ = Const x
你能想到任何有用的应用程序吗?
它违反了左身份法则:return x >>= f
必须相同f x
,但要考虑f x = Const (x + 1)
。
ehird 的回答解释了问题中的实例有什么问题。这里有一个更深入的解释,说明为什么没有其他实例可以工作,即使您要选择除 之外的约束Monoid
,除非该类型只有一个居民(例如,()
)。任何给定类型要么有零个居民,要么有一个居民,要么至少有两个居民。
你可以写这个总函数,一个明显的矛盾:
{-# LANGUAGE EmptyCase #-}
oops :: void
oops = case getConst (return () :: Const TheEmptyType ()) of {}
这种特殊情况实际上是可能的:它与Proxy
. 为了完整起见,这里是:
instance Monad (Const ()) where
return _ = Const ()
Const () >>= _ = Const ()
让x
并y
成为您选择的类型的两个不同的居民。编写这个辅助函数:
f False = Const x
f True = Const y
现在考虑左恒等律的这两个实例:
return False >>= f = f False
return True >>= f = f True
通过参数化,没有办法实现return
andreturn False
是return True
不同的,所以你最终得到相同的值必须等于Const x
and Const y
,这是一个矛盾,因为我们之前说过x
andy
是不同的。