Search code examples
haskellgeneric-programming

How can I use generics to extract all values of a particular type?


I have a data type like this:

data MyType = Foo Bool
            | Bar
            | Baz Bool (Maybe String) Bool
            | Quux Int String

Can I use generics to write a function getBools :: MyType -> [Bool] that returns a list of all the boolean fields in the input?

I came up with this type signature:

getAllOfType ::
  (Generic inner, Generic outer, HasDatatypeInfo inner, All2 HasDatatypeInfo (Code outer)) =>
  Proxy inner -> outer -> [inner]

Using generics-sop, but I don't think that's right. Comparing the DatatypeInfos is not going to convince the type checker that the two types are equivalent.


Solution

  • Using uniplate:

    {-# LANGUAGE DeriveDataTypeable #-}
    
    module M where
    
    import Data.Data
    import Data.Generics.Uniplate.Data
    
    data MyType
      = Foo Bool
      | Bar
      | Baz Bool (Maybe String) Bool
      | Quux Int String
      deriving Data
    
    getBools :: MyType -> [Bool]
    getBools = universeBi