Skip to content

michaeljklein/Equirecursive

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

59 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Limited equirecursive types for Haskell.

Haskell really doesn't support equirecursive types, so we cheat a bit.

This package has three main parts:

  • A type checker for monomorphic equirecursive types, using type families
  • A number of methods for testing type families
  • A nice collection of example and practical modules that require equirecursive types

So, how do we cheat? Consider an implementation of repeat 0 using tuples:

λ> let zeroes = let x = (0, x) in x

Functionally, thanks to Haskell's laziness, this won't loop forever unless you try to access the whole thing at once. However, a problem arises when you look at it's type

zeroes :: Num a => (a, (a, (a, (a, ...

GHCI: Occurs check: cannot construct the infinite type: t3 ~ (t2, t3)

There's a way around this, by using unsafeCoerce and Any:

λ> let zeroesGenerator = (unsafeCoerce (\x -> (0, x)) :: (Int, Any) -> (Int, Any))
zeroesGenerator ∷ (Int, Any) → (Int, Any)

λ> let zeroes = fix zeroesGenerator
zeroes ∷ (Int, Any)

λ> fst zeroes
0

λ> fst (unsafeCoerce (snd zeroes) :: (Int, Any))
0

It actually works! Thanks to Haskell's laziness, zeroes is represented as (Int, thunk), and we can step forward a single step in the thunk's evaluation to get: (Int, (Int, thunk)).

Releases

No releases published

Packages

No packages published