-
-
Save kittinunf/222410d8e30927274fc8302d2978ead7 to your computer and use it in GitHub Desktop.
Object Algebras in Kotlin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Basic setup | |
interface Exp | |
data class Lit(val x: Int): Exp | |
data class Add(val x: Exp, val y: Exp): Exp | |
interface IntAlg<A> | |
{ | |
fun lit(x: Int): A | |
fun add(x: A, y: A): A | |
} | |
open class IntFactory: IntAlg<Exp> | |
{ | |
override fun lit(x: Int) = Lit(x) | |
override fun add(x: Exp, y: Exp) = Add(x, y) | |
} | |
fun <A> exp(v: IntAlg<A>) = v.add(v.lit(42), v.lit(0x52)) | |
val exp0: Exp = exp(IntFactory()) | |
// Adding a print operation | |
interface Print { fun print(): String } | |
// Can I haz SAM-conversion plz? | |
fun Print(f: () -> String) = object: Print { override fun print() = f() } | |
open class IntPrint: IntAlg<Print> | |
{ | |
override fun lit(x: Int) = Print { x.toString() } | |
override fun add(x: Print, y: Print) = Print { "${x.print()} + ${y.print()}" } | |
} | |
val exp1: Print = exp(IntPrint()) | |
// Adding new data variants | |
data class Bool(val x: Boolean): Exp | |
data class Iff(val x: Exp, val y: Exp, val z: Exp): Exp | |
interface IntBoolAlg<A>: IntAlg<A> | |
{ | |
fun bool(b: Boolean): A | |
fun iff(x: A, y: A, z: A): A | |
} | |
open class IntBoolFactory: IntFactory(), IntBoolAlg<Exp> | |
{ | |
override fun bool(x: Boolean) = Bool(x) | |
override fun iff(x: Exp, y: Exp, z: Exp) = Iff(x, y, z) | |
} | |
fun <A> exp2(v: IntBoolAlg<A>) = v.iff(v.bool(false), exp(v), v.lit(0)) | |
val exp2: Exp = exp2(IntBoolFactory()) | |
// Making the data variants printable | |
open class IntBoolPrint: IntPrint(), IntBoolAlg<Print> | |
{ | |
override fun bool(b: Boolean) = Print { b.toString() } | |
override fun iff(x: Print, y: Print, z: Print) | |
= Print { "if (${x.print()}) then ${y.print()} else ${z.print()}" } | |
} | |
val exp3: Print = exp2(IntBoolPrint()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment