Last active
January 10, 2025 21:30
-
-
Save nrinaudo/64b3df262cb5abcdb813ea034e4ef901 to your computer and use it in GitHub Desktop.
Intuition for a typed environment
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
// - Elem -------------------------------------------------------------------------------------------------------------- | |
// --------------------------------------------------------------------------------------------------------------------- | |
sealed trait Elem[X, XS <: Tuple]: | |
def get(haystack: XS): X | |
object Elem: | |
case class Here[X, XS <: Tuple]() extends Elem [X, X *: XS]: | |
def get(haystack: X *: XS) = haystack.head | |
case class There[H, X, T <: Tuple](elem: Elem[X, T]) extends Elem[X, H *: T]: | |
def get(haystack: H *: T) = elem.get(haystack.tail) | |
// - Types ------------------------------------------------------------------------------------------------------------- | |
// --------------------------------------------------------------------------------------------------------------------- | |
enum Type: | |
case Num | |
case Bool | |
object Type: | |
type Num = Num.type | |
type Bool = Bool.type | |
enum TypeRepr[X]: | |
case Num extends TypeRepr[Type.Num] | |
case Bool extends TypeRepr[Type.Bool] | |
// - Environment ------------------------------------------------------------------------------------------------------- | |
// --------------------------------------------------------------------------------------------------------------------- | |
case class Env[XS <: Tuple](data: List[Env.Binding[?, XS]]): | |
def lookup[X](name: String, repr: TypeRepr[X]): Either[String, Elem[X, XS]] = | |
data.find(_.name == name).toRight(s"Binding not found: $name").flatMap: | |
case Env.Binding(_, `repr`, location) => Right(location) | |
case _ => Left(s"Incorrect type: $name") | |
def bind[X](name: String, repr: TypeRepr[X]): Env[X *: XS] = | |
val newBinding = Env.Binding[X, X *: XS](name, repr, Elem.Here()) | |
val newData: List[Env.Binding[?, X *: XS]] = data.map: binding => | |
binding.copy(location = Elem.There(binding.location)) | |
Env(newBinding :: newData) | |
object Env: | |
val empty: Env[EmptyTuple] = Env(List.empty) | |
case class Binding[X, XS <: Tuple](name: String, repr: TypeRepr[X], location: Elem[X, XS]) | |
// - Demo -------------------------------------------------------------------------------------------------------------- | |
// --------------------------------------------------------------------------------------------------------------------- | |
object Run extends App: | |
val env = Env.empty | |
val env2 = env.bind("i", TypeRepr.Num) | |
val env3 = env2.bind("b", TypeRepr.Bool) | |
val env4 = env3.bind("j", TypeRepr.Num) | |
println(env2.lookup("i", TypeRepr.Num)) // Right(Here()) | |
println(env4.lookup("i", TypeRepr.Num)) // Right(There(There(Here())) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment