More sketching.
This commit is contained in:
parent
6489b1f1a3
commit
342b477896
144
sketching/hkt.dm
144
sketching/hkt.dm
@ -1,112 +1,88 @@
|
|||||||
pub hkt Monoid<T has A> {
|
|
||||||
identity: T
|
|
||||||
fn concat(first_item: A, second_item: A): T
|
|
||||||
}
|
|
||||||
|
|
||||||
pub hkt Monad<T has A> {
|
|
||||||
fn <B> map(mapper: fn (item: A): B): T<B>
|
|
||||||
fn <B> flat_map(mapper: fn (item: A): T<B>): T<B>
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use this one!
|
// Use this one!
|
||||||
pub hkt Identity(a: A) {
|
pub int Unit
|
||||||
fn identity() = a
|
|
||||||
|
pub hkt Identity {
|
||||||
|
fn identity() = Self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub hkt Monoid(a: A) : Identity(a) {
|
pub int Addable<T : Addable<T>> {
|
||||||
|
fn op+(other: T): T
|
||||||
|
}
|
||||||
|
|
||||||
|
pub hkt Monoid<A : Addable<A>>(a: A) : Identity {
|
||||||
fn concat(other: Self) = Self(a + other.a)
|
fn concat(other: Self) = Self(a + other.a)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub hkt Monad1(a: A) {
|
pub hkt Monad1<A>(item: A) {
|
||||||
fn <B> map(mapper: fn (from: A): B) = Self(mapper(a))
|
fn <B> map(m: fn (from: A): B) = item is A ? Self(m(item)) : self
|
||||||
fn <B> flat_map(mapper: fn (from: A): T<B>) = Self(mapper(b)?)
|
fn <B> flat_map(m: fn (from: A): T<B>) = item is A ? m(item) : self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub hkt Monad2<T has A, B> : Monad2<T> {
|
pub hkt Monad2<A, B>(item: A | B) : Monad1<A>(item is A ? item : Unit) {
|
||||||
fn map_right(mapper: fn (right: B): B): T
|
fn map_right(m: fn (right: B): B) = item is B ? Self(m(item)) : self
|
||||||
fn flat_map_right(mapper: fn (right: B): T): T
|
fn flat_map_right(m: fn (right: B): Self) = item is B ? m(item) : self
|
||||||
fn fold_right(folder: fn (right: B): A): T
|
fn fold_right(f: fn (right: B): A) = item is B ? Self(f(item)) : self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub hkt Reader<T has A...> : Monad<T> {
|
pub hkt Reader2<R, A, B>(readable: R, item: A, other: B) : Monad2<A, B>(item) {
|
||||||
impl fn map(mapper) = Self(mapper(self))
|
fn read(reader: fn (readable: R): A) = Self(readable, reader(readable), other)
|
||||||
impl fn flat_map(mapper) = mapper(self)?
|
fn use(user: fn (readable: R): Unit) = Self(readable, user(readable), other)
|
||||||
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<T> : Monad1 {
|
pub enum type Option<T> : Monad1 {
|
||||||
Some(item: T) {
|
Some(item),
|
||||||
impl fn map(mapper) = Success(mapper(item))
|
None
|
||||||
impl fn flat_map(mapper) = mapper(item)?
|
|
||||||
},
|
|
||||||
None {
|
|
||||||
impl fn map = self
|
|
||||||
impl fn flat_map = self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum type IO<T, E> : Monad2 {
|
pub enum type IO<T, E> : Monad2 {
|
||||||
Success(item: T) {
|
Success(item: T),
|
||||||
impl fn map(mapper) = Success(mapper(item))
|
Failure(error: E)
|
||||||
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
|
// usage in a file interface
|
||||||
decl pub fn open_file(name: String): FileReader<IO<File, Error>>
|
pub fn open_file(name: String): FileReader<Unit> {
|
||||||
|
try {
|
||||||
|
let file: LuaObject = lua {% fs.open(${name}) %}
|
||||||
|
return Success(
|
||||||
|
File {
|
||||||
|
name,
|
||||||
|
impl fn read_data() {
|
||||||
|
lua {% ${file}.readAll() %}
|
||||||
|
}
|
||||||
|
impl fn close() {
|
||||||
|
lua {% ${file}.close() %}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Unit
|
||||||
|
)
|
||||||
|
} catch (e: LuaError) {
|
||||||
|
return Failure(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum type FileReader<R, E> : Reader2<File, R, E> {
|
||||||
|
Success(file: File, result: R) : Super(file, result, Unit),
|
||||||
|
Failure(error: E) : Super(file, Unit, error)
|
||||||
|
}
|
||||||
|
|
||||||
pub int File {
|
pub int File {
|
||||||
name: String
|
name: String
|
||||||
fn read_data(): IO<String, Error>
|
fn read_data(): String
|
||||||
fn close: IO<Void, Error>
|
fn close()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type FileReader : Reader<IO<File, Error>> {
|
// usage in a main file, perhaps
|
||||||
fld io: IO<File, Error>
|
|
||||||
|
|
||||||
impl fn bind(file) {
|
match open_file('test.txt')
|
||||||
io = Success(file)
|
.read { f -> f.read_data() }
|
||||||
}
|
.map { data -> data.length() }
|
||||||
|
{
|
||||||
impl fn bind_from(producer) {
|
Success(file, length) => {
|
||||||
io = Success(producer())
|
f.close()
|
||||||
}
|
println(result)
|
||||||
|
},
|
||||||
impl fn bind_from_map(mapper) {
|
Failure(error) => {
|
||||||
io = Success(mapper(io?))
|
println(error.message)
|
||||||
}
|
|
||||||
|
|
||||||
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<IO<File, Error>>
|
|
||||||
.flat_map { f -> f.read_data() } // FileReader<IO<String, Error>>
|
|
||||||
.use { f -> f.close() } // FileReader<IO<String, Error>>
|
|
||||||
.ask()? // String
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user