diff --git a/sketching/hkt.dm b/sketching/hkt.dm new file mode 100644 index 0000000..3f3065d --- /dev/null +++ b/sketching/hkt.dm @@ -0,0 +1,112 @@ +pub hkt Monoid { + identity: T + fn concat(first_item: A, second_item: A): T +} + +pub hkt Monad { + fn map(mapper: fn (item: A): B): T + fn flat_map(mapper: fn (item: A): T): T +} + +// Use this one! +pub hkt Identity(a: A) { + fn identity() = a +} + +pub hkt Monoid(a: A) : Identity(a) { + fn concat(other: Self) = Self(a + other.a) +} + +pub hkt Monad1(a: A) { + fn map(mapper: fn (from: A): B) = Self(mapper(a)) + fn flat_map(mapper: fn (from: A): T) = Self(mapper(b)?) +} + +pub hkt Monad2 : Monad2 { + fn map_right(mapper: fn (right: B): B): T + fn flat_map_right(mapper: fn (right: B): T): T + fn fold_right(folder: fn (right: B): A): T +} + +pub hkt Reader : Monad { + impl fn map(mapper) = Self(mapper(self)) + impl fn flat_map(mapper) = mapper(self)? + fn bind(item: A): Self + fn bind_from(item_producer: fn (): A): Self + fn bind_from_map(item_mapper: fn (item: A): A): Self + fn bind_from_flat_map(item_mapper: fn (item: A): T): Self + fn ask(): A + fn use(user: fn (item: A): T): Self +} + +pub enum type Option : Monad1 { + Some(item: T) { + impl fn map(mapper) = Success(mapper(item)) + impl fn flat_map(mapper) = mapper(item)? + }, + None { + impl fn map = self + impl fn flat_map = self + } +} + +pub enum type IO : Monad2 { + Success(item: T) { + impl fn map(mapper) = Success(mapper(item)) + impl fn flat_map(mapper) = mapper(item)? + impl fn map_right(mapper) = self + impl fn flat_map_right(mapper) = self + impl fn fold_right(folder) = self + }. + Failure(error: E) { + impl fn map(mapper) = self + impl fn flat_map(mapper) = self + impl fn map_right(mapper) = Failure(mapper(error)) + impl fn flat_map_right(mapper) = mapper(error)? + impl fn fold_right(folder) = Success(folder(error)) + } +} + +// usage in a file interface +decl pub fn open_file(name: String): FileReader> + +pub int File { + name: String + fn read_data(): IO + fn close: IO +} + +pub type FileReader : Reader> { + fld io: IO + + impl fn bind(file) { + io = Success(file) + } + + impl fn bind_from(producer) { + io = Success(producer()) + } + + impl fn bind_from_map(mapper) { + io = Success(mapper(io?)) + } + + impl fn bind_from_flat_map(flat_mapper) { + io = Success(flat_mapper(io?)?) + } + + impl fn ask() = io? + + impl fn use(user) = { + user(io?) + self + } +} + +// some other file + +open_file('test.txt') // FileReader> + .flat_map { f -> f.read_data() } // FileReader> + .use { f -> f.close() } // FileReader> + .ask()? // String +