generic-aeson-0.1: src/Generics/Generic/IsEnum.hs
{-# LANGUAGE
FlexibleContexts
, FlexibleInstances
, ScopedTypeVariables
, TypeOperators
#-}
-- | Test if a data type is an enumeration (only zero-argument
-- constructors) generically using "GHC.Generics".
module Generics.Generic.IsEnum
( isEnum
, GIsEnum (..)
) where
import Data.Proxy
import GHC.Generics
-- | Class for testing if the functors from "GHC.Generics" are
-- enumerations. You generally don't need to give any custom
-- instances. Just call 'isEnum'.
class GIsEnum f where
gIsEnum :: Proxy (f a) -> Bool
instance GIsEnum V1 where
gIsEnum _ = False
instance GIsEnum (K1 i a) where
gIsEnum _ = False
instance GIsEnum U1 where
gIsEnum _ = True
instance GIsEnum Par1 where
gIsEnum _ = False
-- should be K1 R
instance GIsEnum (Rec1 f) where
gIsEnum _ = False
instance (GIsEnum f, GIsEnum g) => GIsEnum (f :+: g) where
gIsEnum _ = gIsEnum (Proxy :: Proxy (f a)) && gIsEnum (Proxy :: Proxy (g a))
instance (GIsEnum f, GIsEnum g) => GIsEnum (f :*: g) where
gIsEnum _ = False
instance GIsEnum f => GIsEnum (M1 C c f) where
gIsEnum _ = gIsEnum (Proxy :: Proxy (f a))
instance GIsEnum (M1 S c a) where
gIsEnum _ = False
instance GIsEnum f => GIsEnum (M1 D c f) where
gIsEnum _ = gIsEnum (Proxy :: Proxy (f a))
-- instance GIsEnum (f :.: g) where
-- | Generically test if a data type is an enumeration.
isEnum :: forall a. (Generic a, GIsEnum (Rep a)) => Proxy a -> Bool
isEnum _ = gIsEnum (Proxy :: Proxy ((Rep a) a))