Search code examples
haskellcombinatoricsgadt

Enumeration of GADTs in Haskell


Could you please tell me are there any extensions of Haskell deriving mechanism for Enum class? I mean there are a lot of reasonable situations besides ``nullary constructors'' case. Are there any works on this topic?


Solution

  • Do you really need GADTs? Or do you merely want to lift the restriction to a plain enumeration type with only nullary constructors? If the latter, then there are options. One is to use GHC's Generic mechanism together with an implementation of a suitably generic enumeration class. This is available in the generic-deriving package. Here is an example:

    {-# LANGUAGE DeriveGeneric #-}
    import Generics.Deriving
    
    data Tree a = Leaf a | Node (Tree a) (Tree a)
      deriving (Show, Generic)
    
    instance GEnum Bool
    instance GEnum a => GEnum (Tree a)
    
    test :: [Tree Bool]
    test = take 10 genum
    

    Now, test is the following list:

    [ Leaf False
    , Node (Leaf False) (Leaf False)
    , Leaf True
    , Node (Leaf False) (Node (Leaf False) (Leaf False))
    , Node (Node (Leaf False) (Leaf False)) (Leaf False)
    , Node (Leaf False) (Leaf True)
    , Node (Node (Leaf False) (Leaf False)) (Node (Leaf False) (Leaf False))
    , Node (Leaf True) (Leaf False),Node (Leaf False) (Node (Leaf False) (Node (Leaf False) (Leaf False)))
    , Node (Node (Leaf False) (Leaf False)) (Leaf True)
    ]
    

    This implementation of genum uses diagonalization to merge products. This guarantees that every value actually appears somewhere in the list, but may lead to a surprising order in turn.