Skip to content

부록 C: 포인트프리 유틸리티

본 부록에서는 서적에서 설명된 고전적인 자바스크립트 함수의 포인트프리 버전을 확인할 수 있습니다. 다음의 모든 함수는 연습 문제에서 전역 컨텍스트의 일부로 제공되지만, 주의할 점은 이 구현체들이 최적화된 성능이나 효율성을 보장하지 않는다는 것입니다. 이 함수들은 순수 교육 목적으로만 사용됩니다.

프로덕션 환경에 적합한 함수를 찾고 싶다면 다음 라이브러리를 참고하십시오: ramda, lodash, 또는 folktale

본 문서의 함수들은 부록 A에 정의된 currycompose 함수를 참조합니다

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