经常会访问首个(nth(0))和最后一个(nth(-1))元素,所以 Ramda 为这两种特殊情形提供的便捷方法:head 和 last。还提供了访问除首个元素之外的所有元素的函数:tail,除最后一个元素之外的所有元素的方法:init,前 N 个元素:take(N),后 N 个元素:takeLast(N)。来看看这些函数的实例。
const water = temperature => cond([ [equals(0), always('water freezes at 0°C')], [equals(100), always('water boils at 100°C')], [T, temp => `nothing special happens at ${temp}°C`] ])(temperature)
现在将其变为 pointfree 风格的:
1 2 3 4 5
const water = cond([ [equals(0), always('water freezes at 0°C')], [equals(100), always('water boils at 100°C')], [T, temp => `nothing special happens at ${temp}°C`] ])
const water = temperature => cond([ [equals(0), always('water freezes at 0°C')], [equals(100), always('water boils at 100°C')], [T, temp => `nothing special happens at ${temp}°C`] ])(temperature)
我目前还不需要在 Ramda 代码中使用 cond。但我很多年前编写过 Common Lisp 代码,所以 cond 函数感觉就像是位老朋友。
// Full function version: functionpublishedInYear(year) { returnfunction(book) { return book.year === year } } // Arrow function version: const publishedInYear = year =>book => book.year === year
class (Functorf) => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b
Applicative 中定义了 pure 和 <*>
Applicative Functor 的几个实例
Maybe
1 2 3 4
instanceApplicativeMaybewhere pure = Just Nothing <*> _ = Nothing (Just f) <*> something = fmap f something
Applicative 相较于 Functor 的改进之处:
with the Applicative type class, we can chain the use of the <*> function, thus enabling us to seamlessly operate on several applicative values instead of just one. For instance, check this out:
1
pure(+) <*> Just3 <*> Just5-- Just 8
lift 相当于 pure
Applicative 中还定义了 <$>
<$> 相当于中缀版的 fmap,但应用于 Applicative 的链式调用特别方便
1 2 3
(<$>) :: (Functor f) => (a -> b) -> f a -> f b f <$> x = fmap f x -- pure f <*> x <*> y <*> ... === fmap f x <*> y... === f <$> x <*> y...
List 也是 Applicative Functor
1 2 3
instanceApplicative [] where pure x = [x] fs <*> xs = [f x | f <- fs, x <- xs]
理解了 haskell 中 List 的 <*> 也就理解了 Ramda 中的 liftN
将 fs 中的每个 f map 到 xs 中的每个 x。
pure id <*> v = v -- Identity pure f <*> pure x = pure (f x) -- Homomorphism u <*> pure y = pure ($ y) <*> u -- Interchange pure (.) <*> u <*> v <*> w = u <*> (v <*> w) -- Composition