Last active
June 7, 2022 20:50
-
-
Save monadplus/38ccf8ed6e8618efe7074c93a6f6db74 to your computer and use it in GitHub Desktop.
Haskell: type constructor name as symbol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -- | Type constructor name | |
| type TyConsName :: (Type -> Type) -> Symbol | |
| type family TyConsName rep where | |
| TyConsName (D1 (MetaData tyConName _ _ _) _) = tyConName | |
| -- | 'KnownSymbol s' for the 'TyConsName' of 'a' | |
| type Render :: Type -> Constraint | |
| type Render a = KnownSymbol (TyConsName (Rep a)) | |
| -- | Given a 'Generic a', returns the name of its type constructor. | |
| render :: forall a. Render a => String | |
| render = symbolVal (Proxy @(TyConsName (Rep a))) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| {-# LANGUAGE AllowAmbiguousTypes #-} | |
| {-# LANGUAGE DataKinds #-} | |
| {-# LANGUAGE DefaultSignatures #-} | |
| {-# LANGUAGE DeriveAnyClass #-} | |
| {-# LANGUAGE DeriveGeneric #-} | |
| {-# LANGUAGE DerivingStrategies #-} | |
| {-# LANGUAGE DerivingVia #-} | |
| {-# LANGUAGE GADTs #-} | |
| {-# LANGUAGE RankNTypes #-} | |
| {-# LANGUAGE StandaloneKindSignatures #-} | |
| {-# LANGUAGE TypeApplications #-} | |
| {-# LANGUAGE TypeFamilies #-} | |
| {-# LANGUAGE UndecidableInstances #-} | |
| {-# OPTIONS_GHC -Werror #-} | |
| {-# OPTIONS_GHC -Wincomplete-patterns #-} | |
| module Scratch where | |
| import Data.Kind (Constraint, Type) | |
| import Data.Proxy | |
| import GHC.Generics | |
| import GHC.TypeLits | |
| import Data.Char (isUpper) | |
| -- | Type constructor name | |
| type TyConsName :: (Type -> Type) -> Symbol | |
| type family TyConsName rep where | |
| TyConsName (D1 (MetaData tyConName _ _ _) _) = tyConName | |
| -- | 'KnownSymbol s' for the 'TyConsName' of 'a' | |
| type TyConsNameC a = KnownSymbol (TyConsName (Rep a)) | |
| -- | Given a 'Generic a', returns the name of its type constructor. | |
| tyConsName :: forall a. TyConsNameC a => String | |
| tyConsName = symbolVal (Proxy @(TyConsName (Rep a))) | |
| -- | Class for rendering types. | |
| type Render :: Type -> Constraint | |
| class Render a where | |
| render :: String | |
| default render :: TyConsNameC a => String | |
| render = tyConsName @a | |
| -- | Rendering options | |
| data RenderOption | |
| = All | |
| | CapitalLetters | |
| -- | Deriving via helper | |
| type CustomRender :: RenderOption -> Type -> Type | |
| data CustomRender option a = Custom {unCustom :: a} | |
| instance forall a. TyConsNameC a => Render (CustomRender All a) where | |
| render = tyConsName @a | |
| instance forall a. TyConsNameC a => Render (CustomRender CapitalLetters a) where | |
| render = filter isUpper $ tyConsName @a | |
| data Example = Example {runExample :: String} | |
| deriving stock (Generic) | |
| deriving anyclass (Render) | |
| data ThisIsAnExample = ThisIsAnExample { thisIsAnExample :: String} | |
| deriving stock (Generic) | |
| deriving (Render) via (CustomRender All ThisIsAnExample) | |
| data ThisIsAnotherExample = ThisIsAnotherExample { thisIsAnotherExample :: String} | |
| deriving stock (Generic) | |
| deriving (Render) via (CustomRender CapitalLetters ThisIsAnotherExample) | |
| main = do | |
| print $ render @Example | |
| print $ render @ThisIsAnExample | |
| print $ render @ThisIsAnotherExample |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment