-- SPDX-FileCopyrightText: 2020 Tocqueville Group -- -- SPDX-License-Identifier: LicenseRef-MIT-TQ {-# OPTIONS_GHC -Wno-orphans #-} -- | Additional functionality for 'named' package. module Util.Named ( (:!) , (:?) , (.!) , (.?) , (<.!>) , (<.?>) , ApplyNamedFunctor , NamedInner , KnownNamedFunctor (..) ) where import Control.Lens (Iso', Wrapped(..), iso) import Data.Aeson (FromJSON, ToJSON) import Data.Data (Data) import qualified Data.Kind as Kind import Fmt (Buildable(..)) import GHC.TypeLits (KnownSymbol, symbolVal) import Named ((:!), (:?), Name, NamedF(..)) import qualified Text.Show import Util.Label (Label) (.!) :: Name name -> a -> NamedF Identity a name (.!) _ = ArgF . Identity (.?) :: Name name -> Maybe a -> NamedF Maybe a name (.?) _ = ArgF (<.!>) :: Functor m => Name name -> m a -> m (NamedF Identity a name) (<.!>) name = fmap (name .!) infixl 4 <.!> (<.?>) :: Functor m => Name name -> m (Maybe a) -> m (NamedF Maybe a name) (<.?>) name = fmap (name .?) infixl 4 <.?> type family ApplyNamedFunctor (f :: Kind.Type -> Kind.Type) (a :: Kind.Type) where ApplyNamedFunctor Identity a = a ApplyNamedFunctor Maybe a = Maybe a type family NamedInner (n :: Kind.Type) where NamedInner (NamedF f a _) = ApplyNamedFunctor f a -- | Isomorphism between named entity and the entity itself wrapped into the -- respective functor. namedFL :: Label name -> Iso' (NamedF f a name) (f a) namedFL _ = iso (\(ArgF x) -> x) ArgF class KnownNamedFunctor f where -- | Isomorphism between named entity and the entity itself. namedL :: Label name -> Iso' (NamedF f a name) (ApplyNamedFunctor f a) instance KnownNamedFunctor Identity where namedL l = namedFL l . _Wrapped' instance KnownNamedFunctor Maybe where namedL l = namedFL l ---------------------------------------------------------------------------- -- Instances ---------------------------------------------------------------------------- deriving stock instance Eq (f a) => Eq (NamedF f a name) deriving stock instance Ord (f a) => Ord (NamedF f a name) instance (Show a, KnownSymbol name) => Show (NamedF Identity a name) where show (ArgF a) = symbolVal (Proxy @name) <> " :! " <> show a instance (KnownSymbol name, Buildable (f a)) => Buildable (NamedF f a name) where build (ArgF a) = build (symbolVal (Proxy @name)) <> ": " <> build a deriving stock instance (Typeable f, Typeable a, KnownSymbol name, Data (f a)) => Data (NamedF f a name) deriving newtype instance ToJSON a => ToJSON (NamedF Identity a name) deriving newtype instance ToJSON a => ToJSON (NamedF Maybe a name) deriving newtype instance FromJSON a => FromJSON (NamedF Identity a name) deriving newtype instance FromJSON a => FromJSON (NamedF Maybe a name)