Work on hkt and int.

This commit is contained in:
Jesse Brault 2024-11-26 09:37:40 -06:00
parent 342b477896
commit 1898581888
2 changed files with 85 additions and 69 deletions

View File

@ -1,88 +1,71 @@
// Use this one!
pub int Unit
pub hkt Identity {
fn identity() = Self
pub hkt Monad[T<A>] {
fn <B> map(m: fn (from: A) => B): T<B>
fn <B> flat_map(m: fn (from: A) => T<B>): T<B>
}
pub int Addable<T : Addable<T>> {
fn op+(other: T): T
pub hkt Monad[T<A, B>] : Monad[T<B>] {
fn map_left(m: fn (left: A) => B): T<B>
fn flat_map_left(m: fn (left: A) => T<B>): T<B>
}
pub hkt Monoid<A : Addable<A>>(a: A) : Identity {
fn concat(other: Self) = Self(a + other.a)
}
pub hkt Monad1<A>(item: A) {
fn <B> map(m: fn (from: A): B) = item is A ? Self(m(item)) : self
fn <B> flat_map(m: fn (from: A): T<B>) = item is A ? m(item) : self
}
pub hkt Monad2<A, B>(item: A | B) : Monad1<A>(item is A ? item : Unit) {
fn map_right(m: fn (right: B): B) = item is B ? Self(m(item)) : self
fn flat_map_right(m: fn (right: B): Self) = item is B ? m(item) : self
fn fold_right(f: fn (right: B): A) = item is B ? Self(f(item)) : self
}
pub hkt Reader2<R, A, B>(readable: R, item: A, other: B) : Monad2<A, B>(item) {
fn read(reader: fn (readable: R): A) = Self(readable, reader(readable), other)
fn use(user: fn (readable: R): Unit) = Self(readable, user(readable), other)
}
pub enum type Option<T> : Monad1 {
Some(item),
None
}
pub enum type IO<T, E> : Monad2 {
Success(item: T),
Failure(error: E)
}
// usage in a file interface
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 Option<T> : Monad {
Some(item) {
impl fn map(m) = Some(m(item))
impl fn flat_map(m) = m(item)
},
None {
impl fn map(m) = self
impl fn flat_map(m) = self
}
}
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 enum Either<E, A> : Monad {
Left(e: E) {
impl fn map(m) = self
impl fn flat_map(m) = self
impl fn map_left(m) = Right(m(e))
impl fn flat_map_left(m) = m(e)
},
Right(a: A) {
impl fn map(m) = Right(m(a))
impl fn flat_map(m) = m(a)
impl fn map_left(m) = self
impl fn flat_map_left(m) = self
}
}
// Usage of Either in a file interface.
pub int File {
name: String
fn read_data(): String
fn close()
}
// usage in a main file, perhaps
#target[lua]
impl LuaFile(name: String, fld file: LuaObject) : File {
impl fn read_data() = lua {% ${file}.readAll() %}
impl fn close() = lua {% ${file}.close() %}
}
match open_file('test.txt')
.read { f -> f.read_data() }
.map { data -> data.length() }
{
Success(file, length) => {
f.close()
println(result)
},
Failure(error) => {
println(error.message)
#target[lua]
pub fn open_file(name: String): Either<Error, File> {
try {
Right(LuaFile(name, lua {% fs.open($name) %}))
} catch (e: LuaError) {
Left(e)
}
}
// Usage in a main file, perhaps.
// Note this part would be platform independent.
let data_length = match open_file('test.txt') {
Left(error) => println(error.message),
Right(file) => {
let data_length = f.read_data().length()
f.close()
data_length
}
}
println(data_length)

33
sketching/int.dm Normal file
View File

@ -0,0 +1,33 @@
/* Some basic interfaces, representing some useful functional concepts. */
/**
* Represents a "zero" for addition, for example, or a "one" for multiplication, for example
*/
pub int Identity<A> {
identity: A // a constant prop. By default, all props are immutable.
}
/**
* This shows how to do operator overloading via an interface
*/
pub int Addable<T : Addable<T>> {
fn op+(other: T): T // a function which must be implemented by inheritors
}
/**
* Represents a struct that can do concatenation of values.
*/
pub int Monoid<A> : Identity {
fn concat(first: A, second: A): A
}
decl pub int Number : Addable<Number> // primitive
// example usage
decl fn <T> assert_eq(expected: T, actual: T)
let add_monoid: Monoid<Number> = Monoid {
identity: 0
impl fn concat(a, b) = a + b
}
assert_eq(2, add_monoid.concat(1, 1))