Work on hkt and int.
This commit is contained in:
parent
342b477896
commit
1898581888
119
sketching/hkt.dm
119
sketching/hkt.dm
@ -1,69 +1,40 @@
|
|||||||
// Use this one!
|
pub hkt Monad[T<A>] {
|
||||||
pub int Unit
|
fn <B> map(m: fn (from: A) => B): T<B>
|
||||||
|
fn <B> flat_map(m: fn (from: A) => T<B>): T<B>
|
||||||
pub hkt Identity {
|
|
||||||
fn identity() = Self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub int Addable<T : Addable<T>> {
|
pub hkt Monad[T<A, B>] : Monad[T<B>] {
|
||||||
fn op+(other: T): T
|
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 {
|
pub enum Option<T> : Monad {
|
||||||
fn concat(other: Self) = Self(a + other.a)
|
Some(item) {
|
||||||
}
|
impl fn map(m) = Some(m(item))
|
||||||
|
impl fn flat_map(m) = m(item)
|
||||||
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
|
None {
|
||||||
)
|
impl fn map(m) = self
|
||||||
} catch (e: LuaError) {
|
impl fn flat_map(m) = self
|
||||||
return Failure(e)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum type FileReader<R, E> : Reader2<File, R, E> {
|
pub enum Either<E, A> : Monad {
|
||||||
Success(file: File, result: R) : Super(file, result, Unit),
|
Left(e: E) {
|
||||||
Failure(error: E) : Super(file, Unit, error)
|
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 {
|
pub int File {
|
||||||
name: String
|
name: String
|
||||||
@ -71,18 +42,30 @@ pub int File {
|
|||||||
fn close()
|
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')
|
#target[lua]
|
||||||
.read { f -> f.read_data() }
|
pub fn open_file(name: String): Either<Error, File> {
|
||||||
.map { data -> data.length() }
|
try {
|
||||||
{
|
Right(LuaFile(name, lua {% fs.open($name) %}))
|
||||||
Success(file, length) => {
|
} 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()
|
f.close()
|
||||||
println(result)
|
data_length
|
||||||
},
|
|
||||||
Failure(error) => {
|
|
||||||
println(error.message)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
println(data_length)
|
||||||
|
33
sketching/int.dm
Normal file
33
sketching/int.dm
Normal 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))
|
Loading…
Reference in New Issue
Block a user