{-# OPTIONS -XMultiParamTypeClasses -XFlexibleInstances -XOverlappingInstances #-} -- A type-level environment represented as a typeclass with a single -- opertion that references a value. class Ref e v where ref :: e -> v -- Environments are represented by nested tuples. Variables are -- indexed by type. The first matching type is returned, so shadowing -- (multiple SSA instances of a register) is possible. This uses -- OverlappingInstances to allow ``pattern mathching on types''. instance Ref (v,e') v where ref (v,e) = v -- deref instance Ref e' v' => Ref (v,e') v' where ref (v,e) = ref e -- recurse -- Example newtype R0 a = R0 a deriving Show newtype R1 a = R1 a deriving Show newtype R2 a = R2 a deriving Show type Env1 a = (R1 a, (R0 a, (R0 a, ()))) env1 = (R1 1, (R0 2, (R0 3, ()))) :: Env1 Integer -- Variable lookup then happens by type coercion: refR1 = ref env1 :: R1 Integer refR0 = ref env1 :: R0 Integer ----- The following fails to typecheck -- refR2 = ref env1 :: R2 Integer