Annexe C : Utilitaires Pointfree
Cette annexe présente des versions pointfree de fonctions JavaScript classiques décrites dans le livre. Toutes ces fonctions sont apparemment disponibles dans les exercices en tant que partie du contexte global. Il est important de noter que ces implémentations ne sont pas les plus rapides ni les plus optimisées : elles ont uniquement un but éducatif.
Pour des implémentations adaptées à la production, consultez ramda, lodash ou folktale.
Notez que les fonctions font référence aux fonctions curry et compose définies dans l'Annexe A
add
js
// add :: Number -> Number -> Number
const add = curry((a, b) => a + b);append
js
// append :: String -> String -> String
const append = flip(concat);chain
js
// chain :: Monad m => (a -> m b) -> m a -> m b
const chain = curry((fn, m) => m.chain(fn));concat
js
// concat :: String -> String -> String
const concat = curry((a, b) => a.concat(b));eq
js
// eq :: Eq a => a -> a -> Boolean
const eq = curry((a, b) => a === b);filter
js
// filter :: (a -> Boolean) -> [a] -> [a]
const filter = curry((fn, xs) => xs.filter(fn));flip
js
// flip :: (a -> b -> c) -> b -> a -> c
const flip = curry((fn, a, b) => fn(b, a));forEach
js
// forEach :: (a -> ()) -> [a] -> ()
const forEach = curry((fn, xs) => xs.forEach(fn));head
js
// head :: [a] -> a
const head = xs => xs[0];intercalate
js
// intercalate :: String -> [String] -> String
const intercalate = curry((str, xs) => xs.join(str));join
js
// join :: Monad m => m (m a) -> m a
const join = m => m.join();last
js
// last :: [a] -> a
const last = xs => xs[xs.length - 1];map
js
// map :: Functor f => (a -> b) -> f a -> f b
const map = curry((fn, f) => f.map(fn));match
js
// match :: RegExp -> String -> Boolean
const match = curry((re, str) => re.test(str));prop
js
// prop :: String -> Object -> a
const prop = curry((p, obj) => obj[p]);reduce
js
// reduce :: (b -> a -> b) -> b -> [a] -> b
const reduce = curry((fn, zero, xs) => xs.reduce(fn, zero));replace
js
// replace :: RegExp -> String -> String -> String
const replace = curry((re, rpl, str) => str.replace(re, rpl));reverse
js
// reverse :: [a] -> [a]
const reverse = x => (Array.isArray(x) ? x.reverse() : x.split('').reverse().join(''));safeHead
js
// safeHead :: [a] -> Maybe a
const safeHead = compose(Maybe.of, head);safeLast
js
// safeLast :: [a] -> Maybe a
const safeLast = compose(Maybe.of, last);safeProp
js
// safeProp :: String -> Object -> Maybe a
const safeProp = curry((p, obj) => compose(Maybe.of, prop(p))(obj));sequence
js
// sequence :: (Applicative f, Traversable t) => (a -> f a) -> t (f a) -> f (t a)
const sequence = curry((of, f) => f.sequence(of));sortBy
js
// sortBy :: Ord b => (a -> b) -> [a] -> [a]
const sortBy = curry((fn, xs) => xs.sort((a, b) => {
if (fn(a) === fn(b)) {
return 0;
}
return fn(a) > fn(b) ? 1 : -1;
}));split
js
// split :: String -> String -> [String]
const split = curry((sep, str) => str.split(sep));take
js
// take :: Number -> [a] -> [a]
const take = curry((n, xs) => xs.slice(0, n));toLowerCase
js
// toLowerCase :: String -> String
const toLowerCase = s => s.toLowerCase();toString
js
// toString :: a -> String
const toString = String;toUpperCase
js
// toUpperCase :: String -> String
const toUpperCase = s => s.toUpperCase();traverse
js
// traverse :: (Applicative f, Traversable t) => (a -> f a) -> (a -> f b) -> t a -> f (t b)
const traverse = curry((of, fn, f) => f.traverse(of, fn));unsafePerformIO
js
// unsafePerformIO :: IO a -> a
const unsafePerformIO = io => io.unsafePerformIO();