Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 665
Echo Nolan Avatar asked Jul 21 '17 19:07

Echo Nolan


1 Answers

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
like image 84
soupi Avatar answered Oct 19 '22 02:10

soupi