Skip to content

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));
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();