bra*_*drn 15
一个协函子只是普通Functor
类:
class Functor f where
fmap :: (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)
例如,Maybe
(如您所述):
instance Functor Maybe where
fmap _ Nothing = Nothing
fmap f (Just a) = Just (f a)
Run Code Online (Sandbox Code Playgroud)
但是,还有另一种函子:逆函子。这些定义如下:
class Contravariant f where
contramap :: (a -> b) -> f b -> f a
Run Code Online (Sandbox Code Playgroud)
请注意,与相比fmap
,contramap
已颠倒了b
和的顺序a
:
fmap :: Functor f => (a -> b) -> f a -> f b
contramap :: Contravariant f => (a -> b) -> f b -> f a
-- ^ ^
-- look!
Run Code Online (Sandbox Code Playgroud)
现在,这个疯狂的Contravariant
班级甚至有任何实例吗?嗯,是。例如,这是a的定义Predicate
:
newtype Predicate x = Predicate { decide :: x -> Bool }
Run Code Online (Sandbox Code Playgroud)
换句话说,a Predicate x
是一个计算条件的函数x
。我们可以专注contramap
于Predicate
:
contramap :: (a -> b) -> Predicate b -> Predicate a
Run Code Online (Sandbox Code Playgroud)
等效于:
contramap :: (a -> b) -> (b -> Bool) -> (a -> Bool)
Run Code Online (Sandbox Code Playgroud)
基本上,给定一个Predicate
on b
s和从a
s 到 b
s 的映射,就contramap
可以得到Predicate
on a
。(我将把实现留为练习。)这是一个示例(未经测试):
hasMultChars :: Predicate String
hasMultChars = Predicate $ \x -> length x > 1
showInt :: Int -> String
showInt = show
intHasMultChars :: Predicate Int
intHasMultChars = contramap showInt hasMultChars
Run Code Online (Sandbox Code Playgroud)
事实证明,与正常的协变函子相比,协变函子不那么常见,因此也没有那么有用。因此,实际上,我们忽略了“协变量”,因为在大多数情况下它不会添加任何内容。
协变函子是 \xe2\x80\x9cinside\xe2\x80\x9d 和 \xe2\x80\x9coutside\xe2\x80\x9d 箭头指向同一方向的函子。
\n\nclass Functor f where\n fmap :: (a -> b) -> (f a -> f b)\n
Run Code Online (Sandbox Code Playgroud)\n\n逆变函子是 \xe2\x80\x9cinside\xe2\x80\x9d 和 \xe2\x80\x9coutside\xe2\x80\x9d 箭头指向相反方向的函子。
\n\nclass Contravariant f where\n contramap :: (a -> b) -> (f a <- f b)\n
Run Code Online (Sandbox Code Playgroud)\n\n...或者,使用正确的 Haskell 语法,
\n\n contramap :: (a -> b) -> (f b -> f a)\n
Run Code Online (Sandbox Code Playgroud)\n\n这通常表明参数类型作为数据类型中的函数参数出现在某个地方,例如
\n\ndata DepInt x = DepInt (x -> Int)\n\ninstance Contravariant DepInt where\n contramap f (DepInt g) = DepInt $ g . f\n
Run Code Online (Sandbox Code Playgroud)\n\n相反,如果参数仅按原样出现或出现在函数箭头的右侧,则它是协变函子。大多数函子都是这种情况,这就是为什么该类被简单地称为Functor
.
归档时间: |
|
查看次数: |
291 次 |
最近记录: |