[Haskell-cafe] Trouble understanding records and existential types

Roberto Zunino zunino at di.unipi.it
Sat Jan 27 12:09:41 EST 2007


Brian Hulley wrote:
> Chris Kuklewicz wrote:
>> This is how I would write getLeaves, based on your GADT:
>>
>>> data IsLeaf
>>> data IsBranch
>>>
>>> newtype Node = Node { getNode :: (forall c. ANode c) }
[snip]
> Thanks Chris - that's really neat!
> I see it's the explicit wrapping and unwrapping of the existential that 
> solves the typechecking problem,

Actually, Node is universally quantified. This makes it not inhabitated 
given the ANode GADT.  So, you can consume a Node, but you can not 
produce a non-bottom one.

Existential quantification version:

data IsLeaf
data IsBranch

data Node = forall c . Node ( ANode c )

data ANode :: * -> * where
     Branch :: String -> String -> (ANode a,ANode b) -> [Node] -> ANode 
IsBranch
     Leaf :: String -> String -> ANode IsLeaf

getLeaves :: ANode a -> [ANode IsLeaf]
getLeaves (Branch _ _ (l1,l2) rest) = getLeaves l1 ++ getLeaves l2 ++
                                       concatMap getLeaves' rest
getLeaves x@(Leaf {}) = [x]

getLeaves' :: Node -> [ANode IsLeaf]
getLeaves' (Node x) = getLeaves x


Regards,
Zun.


More information about the Haskell-Cafe mailing list