The Contravariant
family of typeclasses代表Haskell生态系统中的标准和基本抽象:
class Contravariant f where
contramap :: (a -> b) -> f b -> f a
class Contravariant f => Divisible f where
conquer :: f a
divide :: (a -> (b, c)) -> f b -> f c -> f a
class Divisible f => Decidable f where
lose :: (a -> Void) -> f a
choose :: (a -> Either b c) -> f b -> f c -> f a
但是,要理解这些类型类的概念并不容易。我认为,如果您能看到一些反例,将有助于更好地理解这些类型。因此,本着Good examples of Not a Functor/Functor/Applicative/Monad?的精神,我正在寻找可以满足以下要求的对比数据类型示例:
Contravariant
的类型构造函数吗?Contravariant
而不是Divisible
的类型构造函数吗?Divisible
但不是Decidable
的类型构造函数吗?Decidable
的类型构造函数吗?答案 0 :(得分:6)
(部分答案)
newtype F a = K (Bool -> a)
不是协变的(但是,它是协变函子)。
newtype F a = F { runF :: a -> Void }
是协变的,但不能为Divisible
,否则
runF (conquer :: F ()) () :: Void
对于无法确定的可除数,我没有合理的例子。我们可以观察到这样的反例必须是这样的,因为它违反了法律,而不仅是类型签名。确实,如果Divisible F
成立,
instance Decidable F where
lose _ = conquer
choose _ _ _ = conquer
满足方法的类型签名。
在图书馆中,当Const m
是一个等分体时,我们发现m
是可分的。
instance Monoid m => Divisible (Const m) where
divide _ (Const a) (Const b) = Const (mappend a b)
conquer = Const mempty
也许这不是合法的Decidable
吗? (我不确定,它似乎满足Decidable
律,但是库中没有Decidable (Const m)
实例。)
来自图书馆:
newtype Predicate a = Predicate (a -> Bool)
instance Divisible Predicate where
divide f (Predicate g) (Predicate h) = Predicate $ \a -> case f a of
(b, c) -> g b && h c
conquer = Predicate $ const True
instance Decidable Predicate where
lose f = Predicate $ \a -> absurd (f a)
choose f (Predicate g) (Predicate h) = Predicate $ either g h . f
答案 1 :(得分:5)
(偏导数答案?)
我相信@chi是正确的when they hypothesize,Const m
不可能是所有Decidable
Monoid
的合法m
,但我基于出于对Decidable
法律的一些猜测。
在the docs中,我们得到Decidable
法则的诱人提示:
此外,我们希望获得与通常的协变选择(w.r.t Applicative)所满足的分配律相同的知识,并应在此处完全加以表述!
Decidable
和Divisible
应该建立什么样的分配关系?好吧,Divisible
有chosen
,它从元素接受事物中构建了一个产品接受事物,而Decidable
有divided
,从元素接受事物中构建了一个求和事物。接受元素的事物。由于乘积是按总和分配的,所以也许我们寻求的法律将f (a, Either b c)
与f (Either (a, b) (a, c))
关联起来,其值可以分别通过a `divided` (b `chosen` c)
和(a `divided` b) `chosen` (a `divided` c)
来构造。
因此,我假设Decidable
缺失的定律与……类似
a `divided` (b `chosen` c) = contramap f ((a `divided` b) `chosen` (a `divided` c))
where f (x, y) = bimap ((,) x) ((,) x) y
Predicate
,Equivalence
和Op
确实很满意(到目前为止,我花了时间检查了三个Decidable
实例)。
现在,我相信您可以为instance Monoid m => Decidable (Const m)
使用的唯一实例对mempty
使用lose
,对mappend
使用choose
;任何其他选择,则lose
不再是choose
的身份。这意味着上述分配法则简化为
a `mappend` (b `mappend` c) = (a `mappend` b) `mappend` (a `mappend` c)
显然是伪造的在任意Monoid
中是不正确的(尽管正如Sjoerd Visscher所观察到的那样,在某些Monoid
中是正确的-因此Const m
可以如果Decidable
是一个分布的类半身像,仍然是合法的m
。