Skip to content

Instantly share code, notes, and snippets.

@ulfryk
Last active January 22, 2020 14:13
Show Gist options
  • Save ulfryk/bbf14792a778d8280ce68ad631992025 to your computer and use it in GitHub Desktop.
Save ulfryk/bbf14792a778d8280ce68ad631992025 to your computer and use it in GitHub Desktop.
A little JavaScript problem
info > 1..3
log > 1
log > 2
log > 3
info > 1..10
log > 1
log > 2
log > 3
log > 4
log > 5
log > 6
log > 7
log > 8
log > 9
log > 10
info > 1..10 map pow
log > 1
log > 4
log > 9
log > 16
log > 25
log > 36
log > 49
log > 64
log > 81
log > 100
info > reverse 1..10 map pow
log > 100
log > 81
log > 64
log > 49
log > 36
log > 25
log > 16
log > 9
log > 4
log > 1
type Iteratee<T, R> = (head?: T, tail?: List<T>) => R;
type List<T> = <R>(fn: Iteratee<T, R>) => R
function Nil<R, T>(fn: Iteratee<T, R>) { return fn() }
const nil = <T>(): List<T> => Nil
const list = <T>(head: T, tail: List<T> = Nil): List<T> =>
function List<R>(fn: Iteratee<T, R>): R { return fn(head, tail) }
const range = (start: number, end: number, acc = list(end)): List<number> =>
end > start ? range(start, end - 1, list(end - 1, acc)) : acc
const foreach = <T>(listX: List<T>, fn: (item: T) => void): void => {
if (listX !== Nil) {
listX((head: T, tail: List<T>) => {
fn(head)
foreach(tail, fn)
})
}
}
const map = <T, R>(listX: List<T>, fn: (item: T) => R): List<R> =>
listX === Nil ? Nil : listX((head: T, tail: List<T>) =>
list(fn(head), map(tail, fn)))
const lhead = <T>(listX: List<T>): T | null | undefined =>
listX === Nil ? null : listX(head => head)
const ltail = <T>(listX: List<T>): List<T> =>
listX === Nil ? Nil : listX((__, tail) => tail) as List<T>
const reverse = <T, R>(listX: List<T>): List<R> => {
const last = (_: List<T>) => lhead(reverse(_))
const initial = (_: List<T>) => reverse(ltail(reverse(_)))
return listX === Nil ? Nil : listX(
(head: T, tail: List<T>) =>
tail === Nil ? list(head) : list(
last(tail),
reverse(list(head, initial(tail)))
))
}
const tripod = list(1, list(2, list(3)))
console.info('1..3')
foreach(tripod, console.log.bind(console))
console.info('1..10')
foreach(range(1, 10), console.log.bind(console))
console.info('1..10 map pow')
const pow = (n: number) => n * n
foreach(map(range(1, 10), pow), console.log.bind(console))
console.info('reverse 1..10 map pow')
foreach(reverse(map(range(1, 10), pow)), console.log.bind(console))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment