A form of documentation that helps developers understand what a function does.
// toUpper :: String -> String
const toUpper = str => str.toUpperCase()// trim :: String -> String
const trim = str =>
str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '')How functions fit together
trim(toUpper(' foo ')) // 'FOO'// inc :: ???
const inc = x => x + 1Document what functions DON'T do
// identity :: a -> a
const identity = x => x// len :: [a] -> Number
const len = arr => arr.length// max :: Number -> Number -> Number
const max = x => y =>
x > y ? x : y// split :: ???
const split = splitOn => str =>
str.split(splitOn)// always :: ???
const always = x => y => xOther examples: join, add, match, gt
// thrush :: a -> (a -> b) -> b
const thrush = arg => f => f(arg)
thrush("bob")(toUpper) // 'BOB'
// foo :: ???
const foo = thrush('frank')// map :: (a -> b) -> [a] -> b
const map = f => arr => arr.map(f)// pipe :: ((a -> b), (b -> c)) -> a -> c
const pipe = (firstFn, secondFn) =>
arg => secondFn(firstFn(arg))// String -> String
// composed with
// String -> String
// =
// trimUp :: String -> String
const trimUp = pipe(trim, toUpper)pipe(
len, // [a] -> Number
inc // Number -> Number
)(['contents', 'dont', 'matter']) // 4// filter :: ???
const filter = predicate => arr =>
arr.filter(predicate)What are some predicates?
What happens to filter's type when we apply a predicate?
containers, sum types, maybe, either
Resources:
