Echo Nolan
Echo Nolan

Reputation: 1151

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.

Upvotes: 6

Views: 200

Answers (1)

soupi
soupi

Reputation: 1013

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

Upvotes: 6

Related Questions