pub trait Functor[*T] fn map(ftu: fn (t: &*T) -> U) -> Self end pub trait Functor[*L -> *R] fn mapLeft(flr: fn (l: &*L) -> *R) -> Self<*L, *R> end pub enum Option Some(T), None end pub enum Either Left(L), Right(R) end pub impl Functor[*T] for Option fn map(ftu: fn (t: &*T) -> U) -> Self if self is Some(t) then Some(ftu(t)) else None end end end pub impl Functor[*R] for Either<_, *R> fn map(f: fn (t: &*R) -> U) -> Self<_, U> if self is Right(t) then Right(f(t)) else self end end end pub impl Functor[*L -> *R] for Either fn mapLeft(f: fn (l: &*L) -> *R) -> Self<*L, *R> if self is Left(l) then Right(f(l)) else self end end end pub trait Monad[*T] static fn lift(t: *T) -> Self<*T> fn flatMap(f: fn (t: &*T) -> Self) -> Self end pub trait Default static fn default() -> Self end pub trait Empty[*T] static fn empty() -> Self<*T> end pub trait Semigroup[*T] type Other<*T> fn concat(other: &Other<*T>) -> Self<&*T> cons fn consConcat(other: Other<*T>) -> Self<*T> end pub int Iterable fn iter() -> Iterator ref self cons fn consIter() -> ConsIterator end pub int Iterator fn next() -> Option<&T ref self> end pub int ConsIterator fn next() -> Option end pub impl Semigroup[*T] for Iterable<*T> type Other = Iterable<*T> fn concat(other: &Other<*T>) -> Self<*T> let result: Self<*T> = ArrayList(count()) for t in self do result.add(t) end for t in other do result.add(t) end result end cons fn consConcat(other: Other<*T>) -> Self<*T> let result: Self<*T> = ArrayList(count()) for t in self do result.add(t) end for t in other do result.add(t) end result end end pub int List : Iterable fn add(t: T) -> Void end pub impl Functor[*T] for List<*T> fn map(f: (t: &*T) -> U) -> Self let mut result: Self = ArrayList(count()) for t in self do result.add(f(t)) end result end end pub impl Empty[*T] for List<*T> static fn empty() -> List<*T> = ArrayList() end pub inst Monad[*T] for List<*T> static fn lift(t: *T) -> List<*T> let result: List<*T> = ArrayList() result.add(t) result end fn flatMap(f: fn (t: &*T) -> List) -> List let result: List = ArrayList(count()) for t in self do for u in f(t).consIter() do result.add(u) end end result end end pub class ArrayList : List let capacity: USize let mut ts: Array> let count: USize = 0 pub ctor(startCapacity: USize = 10) capacity = startCapacity ts = array(startCapacity, None) end class ArrayListIterator(owner: &ArrayList) /* ref owner (implied by constructor) */ : Iterator let i: USize = 0 impl fn next() -> Option<&T ref self> if owner.ts[i] is Some(t) then i++ Some(t) else None end end end class ConsArrayListIterator(ts: Array>) : ConsIterator let i: USize = 0 impl fn next() -> Option if ts[i] is Some then let wrappedT = mem::take(ts[i], None) i++ wrappedT else None end end end impl fn iter() -> Iterator<&T> ref self ArrayListIterator(&self) end impl cons fn consIter() -> Iterator ConsArrayListIterator(mem::take(ts, arrays::empty())) end impl fn add(t: T) -> Void ts[count] = Some(t) count++ if count == capacity then resize() end end fn resize() -> Void let oldTs = mem::take(&ts, array(capacity * 2, None)) for (i, wrappedT) in oldTs.consIter() do ts[i] = wrappedT end end end pub mod std::core pub mod mem pub native fn take(target: &T, replacement: T) -> T end pub native fn array(capacity: USize, init: fn () -> T) -> Array pub native fn array(capacity: USize) -> Array where T has Default pub fn list(...items: Array) -> List let result = ArrayList(items.capacity()) for item in items.consIter() do result.add(item) end result end end // Other file use std::hkt::{Functor[List], Monad[List]} fn main() let someNums: List = [1, 2, 3, 4, 5] let plusOnes = someNums.map { it + 1 } println plusOnes // 2, 3, 4, 5, 6 let twoOfEach = someNums.flatMap { [it, it] } println twoOfEach // 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 end