{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} {-# OPTIONS -Wall #-} module Main where import GHC.Generics import Data.Kind (Type) import GHC.TypeLits (Symbol) -- Helper stuff type family Append a b where Append '[] ys = ys Append (x : xs) ys = x : Append xs ys -- Type-level list of the constructor names (actually we don't even need the -- names to do the trick below, but why not collect them, yolo) type EnumValues :: Type -> [Symbol] type EnumValues a = GEnumValues (Rep a) type family GEnumValues a where GEnumValues (M1 D _ b) = GEnumValues b GEnumValues (M1 C ('MetaCons name _ _) U1) = '[name] -- this nested type family application needs UndecidableInstances GEnumValues (a :+: b) = Append (GEnumValues a) (GEnumValues b) -- One 'a' for each item in the type-level list 'l' (the values in 'l' are -- unused) data OneForEach l a where End :: OneForEach '[] a (:>) :: a -> OneForEach l a -> OneForEach (t : l) a infixr :> deriving instance Show a => Show (OneForEach l a) -- Your data types data Test1 = ONE | TWO | THREE deriving (Show, Generic) data Test2 = FOUR | FIVE | SIX deriving (Show, Generic) type AlertMap t = OneForEach (EnumValues t) String x :: AlertMap Test1 x = "eins" :> "zwei" :> "drei" :> End main :: IO () main = print x