(|>) = left, right => right(left)
(<<) = (f, g) => x => f(g(x))
(>>) = (f, g) => x => g(f(x))

map = (f, xs) => match xs
  x :: rest -> f(x) :: map(f, rest),
  none -> none

filter = (f,xs) => match xs
  x :: rest -> if f(x) then x :: filter(f,rest) else filter(f,rest),
  none -> none

rev_into = (xs, acc) => match xs
  y :: rest -> rev_into(rest, y :: acc),
  _ -> acc
rev = xs => rev_into(xs, default(xs))

take = (n, xs) => if n <= 0 then default(xs) else match xs
  y :: rest -> y :: take(n-1, rest),
  none -> none

reduce = (f, acc, xs) => match xs
  y :: rest -> reduce(f, f(acc, y), rest),
  _ -> acc

fold = (f, acc, xs) => match xs
  y :: rest -> f(y, fold(f, acc, rest)),
  _ -> acc

assert = args => (
  [val, msg] = match args
    [val,msg] -> [val,msg],
    val -> [val, "assert failed"]

  if val != default(val)
  then val
  else panic msg
)

Object = import "Object"
Actor = import "Actor"

export (|>), (<<), (>>), map, filter, take, rev, reduce, fold, assert, Object, Actor
