我阅读了许多关于contramap的文章,并发现https://hackage.haskell.org/package/contravariant-1.4.1/docs/Data-Functor-Contravariant.html#g:3是最好的。
无论如何,我发现如何使用例如:
*Lib Data.Functor.Contravariant> a = Predicate (\x -> x > 20)
*Lib Data.Functor.Contravariant> :t contramap
contramap :: Contravariant f => (a -> b) -> f b -> f a
*Lib Data.Functor.Contravariant> :t contramap (\x -> x * 2)
contramap (\x -> x * 2) :: (Num b, Contravariant f) => f b -> f b
*Lib Data.Functor.Contravariant> :t contramap (\x -> x * 2) a
contramap (\x -> x * 2) a :: (Ord b, Num b) => Predicate b
*Lib Data.Functor.Contravariant> x = contramap (\x -> x * 2) a
*Lib Data.Functor.Contravariant> getPredicate x 45
True
但是我无法想象它在哪里有用。
在我上面发布的网站上,它说:
而在Haskell中,人们可以将Functor视为包含或生成值,协变Functor是一种可以被视为消耗值的Functor。
看看Functor的定义:
class Functor (f :: * -> *) where
fmap :: (a -> b) -> f a -> f b
它消耗了类型 a
的值,并生成了类型 b
的值。在 contramap
中,它消耗了该值。
class Contravariant (f :: * -> *) where
contramap :: (a -> b) -> f b -> f a
它使用哪种变量类型,a
还是 b
?
还有一个来自于https://www.fpcomplete.com/blog/2016/11/covariance-contravariance的问题,关于正位置和负位置。网站上说:
- 正位置:类型变量是函数的结果/输出/范围/值域
- 负位置:类型变量是函数的参数/输入/定义域
看一下 contramap 类型定义:
contramap :: (a -> b) -> f b -> f a
作者指的是哪种类型的变量?
x :: F A
,其中F
具有Functor F
和一些A
)可以被看作是产生类型为A
的值的计算;而一个逆变函子可以被看作是消耗类型为A
的值。 - user2407038