Skip to content

Commit

Permalink
Add DerivingVia newtype 'BoundedEnum' for extra neatness
Browse files Browse the repository at this point in the history
I think it makes the code more readable, and reduces boilerplate. I did
not replace existing uses of toTextFromBoundedEnum or
fromTextToBoundedEnum. This can be done later now that this exists.
  • Loading branch information
Anviking committed Feb 3, 2020
1 parent a437a5e commit d72461e
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 6 deletions.
9 changes: 3 additions & 6 deletions lib/cli/src/Cardano/CLI.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
Expand Down Expand Up @@ -163,7 +164,7 @@ import Data.Text
( Text )
import Data.Text.Class
( FromText (..), TextDecodingError (..), ToText (..), showT,
toTextFromBoundedEnum, fromTextToBoundedEnum, CaseStyle (..) )
BoundedEnum (..), CaseStyle (..) )
import Data.Text.Read
( decimal )
import Fmt
Expand Down Expand Up @@ -334,12 +335,8 @@ cmdKey = command "key" $ info (helper <*> cmds) $ mempty

data KeyType = Icarus | Trezor | Ledger | Byron
deriving (Show, Eq, Generic, Bounded, Enum)
deriving (ToText, FromText) via (BoundedEnum 'KebabLowerCase KeyType)

instance ToText KeyType where
toText = toTextFromBoundedEnum KebabLowerCase

instance FromText KeyType where
fromText = fromTextToBoundedEnum KebabLowerCase

parseKeyType :: Parser (IO KeyType)
parseKeyType = toIO . fromText <$> strOption
Expand Down
28 changes: 28 additions & 0 deletions lib/text-class/src/Data/Text/Class.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
Expand Down Expand Up @@ -30,6 +32,7 @@ module Data.Text.Class
-- * Helpers
, showT
, splitAtLastOccurrence
, BoundedEnum (..)
) where

import Prelude
Expand All @@ -42,6 +45,7 @@ import Data.List.Extra
( enumerate )
import Data.Maybe
( isNothing, listToMaybe )
import Data.Proxy
import Data.Text
( Text )
import Data.Text.Read
Expand Down Expand Up @@ -191,6 +195,30 @@ fromTextToBoundedEnum cs t =
filter ((== inputInPascalCase) . fst) $
(Just <$> allValuesInPascalCase) `zip` [0 :: Int ..]


-- | Newtype wrapper to derive @ToText@ and @FromText@ using @DerivingVia@.
newtype BoundedEnum (s :: CaseStyle) a = BoundedEnum a

-- Needed to get 'CaseStyle back to the value level
class KnownCaseStyle (s :: CaseStyle) where
caseStyleVal :: Proxy s -> CaseStyle
instance KnownCaseStyle 'CamelCase where caseStyleVal _ = CamelCase
instance KnownCaseStyle 'PascalCase where caseStyleVal _ = PascalCase
instance KnownCaseStyle 'KebabLowerCase where caseStyleVal _ = KebabLowerCase
instance KnownCaseStyle 'SnakeLowerCase where caseStyleVal _ = SnakeLowerCase
instance KnownCaseStyle 'SnakeUpperCase where caseStyleVal _ = SnakeUpperCase
instance KnownCaseStyle 'SpacedLowerCase where caseStyleVal _ = SpacedLowerCase

instance (KnownCaseStyle s, Bounded a, Enum a, Show a)
=> ToText (BoundedEnum s a) where
toText (BoundedEnum x) =
toTextFromBoundedEnum (caseStyleVal (Proxy :: Proxy s)) x

instance (KnownCaseStyle s, Bounded a, Enum a, Show a)
=> FromText (BoundedEnum s a) where
fromText = fmap BoundedEnum .
(fromTextToBoundedEnum (caseStyleVal (Proxy :: Proxy s)))

toCaseStyle :: CaseStyle -> Casing.Identifier String -> String
toCaseStyle = \case
CamelCase -> Casing.toCamel
Expand Down

0 comments on commit d72461e

Please sign in to comment.