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 inst Functor[*T] for Option impl fn map(ftu: fn (t: T) -> U) -> Self if self is Some(t) then Some(ftu(t)) else None end end end pub inst Functor[*T] for Either<_, *T> impl fn map(ftu: fn (t: *T) -> U) -> Self if self is Right(t) then Right(ftu(t)) else self end end end pub inst Functor[*L -> *R] for Either impl fn mapLeft(flr: fn (l: *L) -> *R) -> Self<*L, *R> if self is Left(l) then Right(flr(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] where *T has Default static fn empty() -> Self<*T> end pub trait Semigroup[*T] fn concat(other: &Self<*T>) -> Self<&*T> cons fn consConcat(other: Self<*T>) -> Self<*T> end pub int Iterable fn iter() -> Iterator cons fn consIter() -> ConsIterator end pub int Iterator fn next() -> Option<&T> fn withIndex() -> Iterator> end pub int ConsIterator fn next() -> Option fn withIndex() -> Iterator> end pub int List : Iterable req Monad, Functor, Semigroup, Empty fn add(t: T) -> Void end pub inst Functor[*T] for List<*T> where *T has Default impl fn map(ftu: (t: *T) -> U) -> Self let mut result: Self = Self::empty() for t in self do result += Self::lift(ftu(t)) end result end end pub class ArrayList : List let init: fn () -> T // ?: sugar for Option T> let capacity: USize let mut ts: Array let count: USize = 0 pub ctor(startCapacity: USize = 10, init: fn () -> T = Default::default) where T has Default := init capacity = startCapacity // ?= sugar for Some(expr) ts = array(startCapacity, init) end pub ctor(init: fn () -> T, startCapacity: USize = 10) := init capacity = startCapacity ts = array(startCapacity, init) end impl fn iter() -> Iterator todo() end impl fn add(t: T) -> Void ts[count] = t count++ if count == capacity then resize() end end fn resize() -> Void let oldTs = mem::take(&ts, array(capacity * 2, init)) for (i, t) in oldTs.consIter().withIndex() do ts[i] = t end end end pub inst Empty[*T] for ArrayList<*T> where *T has Default impl static fn empty() -> List<*T> = Self() end pub inst Semigroup[*T] for ArrayList<*T> where *T has Default impl fn concat(other: List<*T>) -> List<*T> let result = Self() for t in self do result.add(t) end for t in other do result.add(t) end result end end pub inst Monad[*T] for ArrayList<*T> where T has Default impl static fn lift(t: *T) -> List<*T> let result: List<*T> = Self() result.add(t) result end impl fn flatMap(f: fn (t: *T) -> List) -> List let result: List = Self() for t in self do for u in f(t) do result.add(u) end end result 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 where T has Default let result = ArrayList(items.capacity(), Default[T]::default) for item in items.consIter() do result.add(item) end result end end // other file use std::collections::List 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