From 189858188894de6055ca1b7aa2def30bdc26d783 Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Tue, 26 Nov 2024 09:37:40 -0600 Subject: [PATCH] Work on hkt and int. --- sketching/hkt.dm | 121 ++++++++++++++++++++--------------------------- sketching/int.dm | 33 +++++++++++++ 2 files changed, 85 insertions(+), 69 deletions(-) create mode 100644 sketching/int.dm diff --git a/sketching/hkt.dm b/sketching/hkt.dm index 71c1a06..af10216 100644 --- a/sketching/hkt.dm +++ b/sketching/hkt.dm @@ -1,88 +1,71 @@ -// Use this one! -pub int Unit - -pub hkt Identity { - fn identity() = Self +pub hkt Monad[T] { + fn map(m: fn (from: A) => B): T + fn flat_map(m: fn (from: A) => T): T } -pub int Addable> { - fn op+(other: T): T +pub hkt Monad[T] : Monad[T] { + fn map_left(m: fn (left: A) => B): T + fn flat_map_left(m: fn (left: A) => T): T } -pub hkt Monoid>(a: A) : Identity { - fn concat(other: Self) = Self(a + other.a) -} - -pub hkt Monad1(item: A) { - fn map(m: fn (from: A): B) = item is A ? Self(m(item)) : self - fn flat_map(m: fn (from: A): T) = item is A ? m(item) : self -} - -pub hkt Monad2(item: A | B) : Monad1(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(readable: R, item: A, other: B) : Monad2(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 : Monad1 { - Some(item), - None -} - -pub enum type IO : Monad2 { - Success(item: T), - Failure(error: E) -} - -// usage in a file interface -pub fn open_file(name: String): FileReader { - 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 : 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 : Reader2 { - Success(file: File, result: R) : Super(file, result, Unit), - Failure(error: E) : Super(file, Unit, error) +pub enum Either : 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 { + 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) diff --git a/sketching/int.dm b/sketching/int.dm new file mode 100644 index 0000000..ab1f555 --- /dev/null +++ b/sketching/int.dm @@ -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 { + identity: A // a constant prop. By default, all props are immutable. +} + +/** + * This shows how to do operator overloading via an interface + */ +pub int Addable> { + 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 : Identity { + fn concat(first: A, second: A): A +} + +decl pub int Number : Addable // primitive + +// example usage +decl fn assert_eq(expected: T, actual: T) + +let add_monoid: Monoid = Monoid { + identity: 0 + impl fn concat(a, b) = a + b +} +assert_eq(2, add_monoid.concat(1, 1)) \ No newline at end of file