{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE UndecidableInstances #-}
module Haskus.Utils.Types.Generics
( module GHC.Generics
, Field
, FieldType
, LookupField
, LookupFieldType
, ExtractFields
, ExtractFieldTypes
)
where
import Haskus.Utils.Types.List
import Haskus.Utils.Types
import GHC.Generics
data Field (name :: Symbol) (t :: *)
type family FieldType f where
FieldType (Field name t) = t
type family LookupFieldType fs s where
LookupFieldType fs s = FieldType (LookupField fs s)
type family LookupField (fs :: [*]) (s :: Symbol) where
LookupField (Field name t ': fs) name = Field name t
LookupField (Field name t ': fs) s = LookupField fs s
LookupField '[] name =
TypeError ('Text "Cannot find field with name: " ':<>: 'ShowType name)
type family ExtractFields (a :: *) where
ExtractFields a = ExtractFields' (Rep a)
type family ExtractFields' a where
ExtractFields' (D1 _ cs) = ExtractFields' cs
ExtractFields' (C1 _ ss) = ExtractFields' ss
ExtractFields' (s1 :*: s2) = Concat (ExtractFields' s1) (ExtractFields' s2)
ExtractFields' (S1 ('MetaSel ('Just name) _ _ _) (Rec0 t)) = '[Field name t]
type family ExtractFieldTypes (a :: *) where
ExtractFieldTypes a = ExtractFieldTypes' (Rep a)
type family ExtractFieldTypes' a where
ExtractFieldTypes' (D1 _ cs) = ExtractFieldTypes' cs
ExtractFieldTypes' (C1 _ ss) = ExtractFieldTypes' ss
ExtractFieldTypes' (s1 :*: s2) =
Concat (ExtractFieldTypes' s1) (ExtractFieldTypes' s2)
ExtractFieldTypes' (S1 _ (Rec0 t)) = '[t]