12-Recursive-Types-Newtypes.purs

module Syntax.Basic.Newtype.Recursive where

-- The following code does not compile because type synonyms are
-- expanded to their definition. So, the following code produces
-- an infinite loop
--
-- data Either l r
--   = Left l
--   | Right r
-- type Foo = { value :: Either Int Foo }
--
-- which expands to...
--  { value :: Either Int Foo }
--  { value :: Either Int { value :: Either Int Foo } }
--  { value :: Either Int { value :: Either Int { value :: Either Int Foo } } }
--  { value :: Either Int { value :: Either Int { value :: Either Int ... } } }

-- We can workaround that problem by wrapping the type in a newtype
data Either l r
  = Left l
  | Right r

newtype Foo = Foo { value :: Either Int Foo }

example1 :: Foo
example1 = Foo { value: Left 1 }

example2 :: Foo
example2 = Foo { value: Right (Foo { value: Left 1 }) }

example3 :: Foo
example3 = Foo { value: Right (Foo { value: Right (Foo { value: Left 1 }) }) }