Skip to content

Commit

Permalink
Improved feature ergonomics
Browse files Browse the repository at this point in the history
  • Loading branch information
newhoggy committed Jul 25, 2023
1 parent e0d3b0e commit fca2ac6
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 46 deletions.
26 changes: 19 additions & 7 deletions cardano-api/gen/Test/Gen/Cardano/Api/Typed.hs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeApplications #-}

{-# OPTIONS_GHC -Wno-deprecations #-}

module Test.Gen.Cardano.Api.Typed
( genFeatureValueInEra
( genFeaturedInEra
, genMaybeFeaturedInEra

, genAddressByron
, genAddressInEra
Expand Down Expand Up @@ -731,16 +734,25 @@ genTxBody era = do
Left err -> fail (displayError err)
Right txBody -> pure txBody

-- | Generate a 'FeatureValue' for the given 'CardanoEra' with the provided generator.
genFeatureValueInEra :: ()
-- | Generate a 'Featured' for the given 'CardanoEra' with the provided generator.
genFeaturedInEra :: ()
=> Alternative f
=> feature era
-> f a
-> f (Featured feature era a)
genFeaturedInEra witness gen =
Featured witness <$> gen

-- | Generate a 'Featured' for the given 'CardanoEra' with the provided generator.
genMaybeFeaturedInEra :: ()
=> FeatureInEra feature
=> Alternative f
=> f a
-> CardanoEra era
-> f (FeatureValue feature era a)
genFeatureValueInEra gen =
featureInEra (pure NoFeatureValue) $ \witness ->
pure NoFeatureValue <|> fmap (FeatureValue witness) gen
-> f (Maybe (Featured feature era a))
genMaybeFeaturedInEra gen =
featureInEra (pure Nothing) $ \witness ->
pure Nothing <|> fmap Just (genFeaturedInEra witness gen)

genTxScriptValidity :: CardanoEra era -> Gen (TxScriptValidity era)
genTxScriptValidity era = case txScriptValiditySupportedInCardanoEra era of
Expand Down
56 changes: 19 additions & 37 deletions cardano-api/internal/Cardano/Api/Feature.hs
Original file line number Diff line number Diff line change
@@ -1,64 +1,46 @@
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}

{-# OPTIONS_GHC -Wno-deprecations #-}

module Cardano.Api.Feature
( FeatureValue (..)
, valueOrDefault
, asFeatureValue
, asFeatureValueInShelleyBasedEra
, isFeatureValue
( Featured (..)
, asFeaturedInEra
, asFeaturedInShelleyBasedEra
) where

import Cardano.Api.Eras

-- | A value of type @'FeatureValue' feature era a@ is either:
data FeatureValue feature era a where
-- | A value is available for this feature in this era
FeatureValue
-- | A value only if the feature is supported in this era
data Featured feature era a where
Featured
:: feature era
-- ^ The witness that the feature is supported in this era
-> a
-- ^ The value to use
-> FeatureValue feature era a

-- | No value is available for this feature in this era
NoFeatureValue
:: FeatureValue feature era a

deriving instance (Eq a, Eq (feature era)) => Eq (FeatureValue feature era a)
deriving instance (Show a, Show (feature era)) => Show (FeatureValue feature era a)
-> Featured feature era a

-- | Determine if a value is defined.
--
-- If the value is not defined, it could be because the feature is not supported or
-- because the feature is supported but the value is not available.
isFeatureValue :: FeatureValue feature era a -> Bool
isFeatureValue = \case
NoFeatureValue -> False
FeatureValue _ _ -> True
deriving instance (Eq a, Eq (feature era)) => Eq (Featured feature era a)
deriving instance (Show a, Show (feature era)) => Show (Featured feature era a)

-- | Get the value if it is defined, otherwise return the default value.
valueOrDefault :: a -> FeatureValue feature era a -> a
valueOrDefault defaultValue = \case
NoFeatureValue -> defaultValue
FeatureValue _ a -> a
instance Functor (Featured feature era) where
fmap f (Featured feature a) = Featured feature (f a)

-- | Attempt to construct a 'FeatureValue' from a value and era.
-- If the feature is not supported in the era, then 'NoFeatureValue' is returned.
asFeatureValue :: ()
asFeaturedInEra :: ()
=> FeatureInEra feature
=> a
-> CardanoEra era
-> FeatureValue feature era a
asFeatureValue value = featureInEra NoFeatureValue (`FeatureValue` value)
-> Maybe (Featured feature era a)
asFeaturedInEra value = featureInEra Nothing (Just . flip Featured value)

-- | Attempt to construct a 'FeatureValue' from a value and a shelley-based-era.
asFeatureValueInShelleyBasedEra :: ()
asFeaturedInShelleyBasedEra :: ()
=> FeatureInEra feature
=> a
-> ShelleyBasedEra era
-> FeatureValue feature era a
asFeatureValueInShelleyBasedEra value = asFeatureValue value . shelleyBasedToCardanoEra
-> Maybe (Featured feature era a)
asFeaturedInShelleyBasedEra value = asFeaturedInEra value . shelleyBasedToCardanoEra
6 changes: 4 additions & 2 deletions cardano-api/src/Cardano/Api.hs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@ module Cardano.Api (
cardanoEraConstraints,
InAnyCardanoEra(..),

-- * Features
-- * Feature support
FeatureInEra(..),
FeatureValue(..),
Featured(..),
asFeaturedInEra,
asFeaturedInShelleyBasedEra,

-- ** Shelley-based eras
ShelleyBasedEra(..),
Expand Down

0 comments on commit fca2ac6

Please sign in to comment.