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 + 1
Document 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 => x
Other 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: