在上一章,我們提到了 Functor,但更精準地說是 Covariant functor,而今天要提到的則是 Contravariant Functor,其定義非常相似
contramap :: Contravariant f => f a ~> (b -> a) -> f b
map :: Functor f => f a ~> (a -> b) -> f b
Type Signature
contramap :: Contravariant f => f a ~> (b -> a) -> f b
Law
對於任何 Contravariant u
都要符合下列兩種特性,
u.contramap(x => x) === u
u.contramap(f).contramap(g) === u.contramap(x => g(f(x)))
Example
來看看一個簡單的範例,首先我們先來建立一個 Contravariant Functors Pred
import * as R from 'ramda';
// contramap :: Pred a ~> (b -> a) -> Pred b
const Pred = run => ({
run,
contramap: g => Pred(R.compose(run, g))
})
// Pred Number
const isEven = Pred(num => num % 2 === 0)
const length = x => x.length
const lengthIsEven = isEven.contramap(length)
lengthIsEven.run('FP') // true
可以看到 lengthIsEven
就是先將 字串 FP
透過 length :: String -> Number
轉換後,就將原本的 Pred Number
轉換成 Pred String
驗證是否符合 fantasy-land 的定義
const exclaim = str => str.concat('!')
// Identity
Pred(isEven).contramap(x => x) === Pred(isEven)
// Composition
Pred(isEven).contramap(length).contramap(exclaim) === Pred(isEven).contramap(x => length(exclaim(x)))
今天太忙了,決定明天再進行補充!!!
NEXT: Functor & Contravariant Functor