deimos-lang/sketching/september_2025/hkt/functor.dm
2025-09-28 12:34:29 -05:00

236 lines
5.0 KiB
Plaintext

pub trait Functor[*T]
fn <U> map(ftu: fn (t: &*T) -> U) -> Self<U>
end
pub trait Functor[*L -> *R]
fn mapLeft(flr: fn (l: &*L) -> *R) -> Self<*L, *R>
end
pub enum Option<T>
Some(T),
None
end
pub enum Either<L, R>
Left(L),
Right(R)
end
pub impl Functor[*T] for Option<T>
fn <U> map(ftu: fn (t: &*T) -> U) -> Self<U>
if self is Some(t) then
Some(ftu(t))
else
None
end
end
end
pub impl Functor[*R] for Either<_, *R>
fn <U> 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<L, R>
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 <U> flatMap(f: fn (t: &*T) -> Self<U>) -> Self<U>
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<T>
fn iter() -> Iterator<T> ref self
cons fn consIter() -> ConsIterator<T>
end
pub int Iterator<T>
fn next() -> Option<&T ref self>
end
pub int ConsIterator<T>
fn next() -> Option<T>
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<T> : Iterable<T>
fn add(t: T) -> Void
end
pub impl Functor[*T] for List<*T>
fn <U> map(f: (t: &*T) -> U) -> Self<U>
let mut result: Self<U> = 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 <U> flatMap(f: fn (t: &*T) -> List<U>) -> List<U>
let result: List<U> = 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<T> : List<T>
let capacity: USize
let mut ts: Array<Option<T>>
let count: USize = 0
pub ctor(startCapacity: USize = 10)
capacity = startCapacity
ts = array(startCapacity, None)
end
class ArrayListIterator<T>(owner: &ArrayList<T>) /* ref owner (implied by constructor) */ : Iterator<T>
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<T>(ts: Array<Option<T>>) : ConsIterator<T>
let i: USize = 0
impl fn next() -> Option<T>
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<T>
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 <T> take(target: &T, replacement: T) -> T
end
pub native fn <T> array(capacity: USize, init: fn () -> T) -> Array<T>
pub native fn <T> array(capacity: USize) -> Array<T> where T has Default
pub fn <T> list(...items: Array<T>) -> List<T>
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<Int> = [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