pub hkt Monad[T] { fn map(m: fn (from: A) => B): T fn flat_map(m: fn (from: A) => 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 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 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() } #target[lua] impl LuaFile(name: String, fld file: LuaObject) : File { impl fn read_data() = lua {% ${file}.readAll() %} impl fn close() = lua {% ${file}.close() %} } #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)