// Num → Num primitive ceiling; // Str → a primitive error; // Num → Num primitive floor; // Natural logarithm. // Num → Num primitive log; // Num → Str primitive numToStr; // Print argument to the console and return it. // a → a primitive debugLog; // Bool → Bool let or = fun { True x → True; False True → True; False False → False }; // Bool → Bool let not = fun { True → False; False → True }; // (b → c) → (a → b) → a → c // Would like infix operators. let compose = fun f g x → f (g x); // a → b → a let const = fun x _ → x; // (a → b) → (a, c) → (b, c) let first = fun f (a, c) → (f a, c); // (a, b) → a let fst = fun (x, y) → x; // List a → a let head = fun [x, ...xs] → x; // a → a let id = fun x → x; // (a → b) → (a → c) → a → (b, c) let prod = fun f g x → (f x, g x); // Num → Num → Ordering let compare = fun (x, y) → match x < y as { True → LT; False → match x > y as { True → GT; False → EQ } }; // List a → List a → List a letrec fun concat { [] ys → ys; [x, ...xs] ys → [x, ...concat xs ys] }; // a → List a → Bool (where a ∈ {Num, Str}) letrec fun elem x { [] → False; [x', ...xs] → or (x == x') (elem x xs) }; // (a → Bool) → List a → List a letrec fun filter p { [] → []; [x, ...xs] → let ys = filter p xs in match p x as { True → [x, ...ys]; False → ys } }; // (a → b → c) → b → a → c let flip = fun f x y → f y x; // ((a, b) → a) → a → List b → a letrec fun foldl op z { [] → z; [x, ...xs] → foldl op (op (z, x)) xs }; // ((a, b) → a) → List b → a letrec fun foldl1 op { [x, ...xs] → foldl op x xs }; // ((a, b) → b) → b → List a → b letrec fun foldr op z { [] → z; [x, ...xs] → op (x, foldr op z xs) }; // ((a, b) → b) → List a → b letrec fun foldr1 op { [x] → x; [x, y, ...xs] → op (x, foldr1 op [y, ...xs]) }; // ((a, b) → a) → a → List b -> List a letrec fun scanl1 op z xs → let go = fun (x, continue) acc → let next = op (acc, x) in [next, ...continue next] in foldr go (const []) xs z; // ((a, b) → a) → a → List b -> List a let scanl = fun op z xs → [z, ...scanl1 op z xs]; // List a → a → List a letrec fun intersperse { [] sep → []; [x] sep → [x]; [x, y, ...ys] sep → [x, sep, ...intersperse [y, ...ys]] }; // List a → a letrec fun last { [x] → x; [x, y, ...xs] → last [y, ...xs] }; // Log of x in base y. // Num → Num → Num let logBase = fun x y → log y / log x; // (a → b) → List a → List b letrec fun map f { [] → []; [x, ...xs] → [f x, ...map f xs] }; // Num → (a → a) → a → List a letrec fun iterate n f z → match n == 0 as { True → []; False → [z, ...map f (iterate (n - 1) f z)] }; // List a → Num letrec fun length { [] → 0; [x, ...xs] → 1 + length xs }; // Num → Num let negate = fun n → 0 - n; // List a → List a letrec fun reverse { [] → []; [x, ...xs] → concat (reverse xs) [x] }; // List (a, b) → (List a, List b) letrec fun unzip { [] → ([], []); [(x, y), ...xys] → match unzip xys as (xs, ys) → ([x, ...xs], [y, ...ys]) }; // ((a, b) → c) → List a → List b → List c letrec fun zipWith op { [] ys → []; [x, ...xs] { [] → []; [y, ...ys] → [op (x, y), ...zipWith op xs ys] } }; let zip = zipWith id; // Num → a → List a let repeat = flip iterate id; // a → List (a, b) → b (where a ∈ {Num, Str}) letrec fun lookup k [(k', v), ...kvs] → match k == k' as { True → v; False → lookup k kvs }; // (Num, Num) → Num let max2 = fun (n, m) → match n > m as { True → n; False → m }; // (Num, Num) → Num let min2 = fun (n, m) → match n < m as { True → n; False → m }; // List Num → Num let max = foldr1 max2; // List Num → Num let min = foldr1 min2; // Expects non-negative integer as first argument and non-empty list as second argument. // Num → List a → a letrec fun nth n [x, ...xs] → match n == 0 as { True → x; False → nth (n - 1) xs }; // Num → Num → Num let ceilingToNearest = fun n m → ceiling (n / m) * m; // (a → b) → (c, a) → (c, b) let second = fun f (c, a) → (c, f a); // (a, b) → b let snd = fun (x, y) → y; // List Num → Num let sum = fun xs → foldr (fun (x, y) → x + y) 0 xs; // (a, b) → (b, a) let swap = fun (a, b) → (b, a); // List a → List a let tail = fun [x, ...xs] → xs; // (a, b) → c) → a → b → c let curry = fun f x y → f (x, y); // (a → b → c) → (a, b) → c let uncurry = fun f (x, y) → f x y; letrec fun take n xs → match n <= 0 as { True → []; False → match xs as { [] → []; [x, ...xs] → [x, ...take (n - 1) xs] } }; letrec fun drop n xs → match n <= 0 as { True → xs; False → match xs as { [] → []; [_, ...xs] → drop (n - 1) xs } }; // Num → List a → List a let lastN = fun n xs → foldl (uncurry (compose const (drop 1))) xs (drop n xs)