-- SPDX-FileCopyrightText: 2020 Tocqueville Group -- -- SPDX-License-Identifier: LicenseRef-MIT-TQ {-# OPTIONS_GHC -Wno-orphans #-} -- | Additional functionality for @named@ package. module Morley.Util.Named ( (!) , (:!) , (:?) , (<:!>) , (<:?>) , ApplyNamedFunctor , NamedInner , KnownNamedFunctor (..) , NamedF (.., (:!), (:?), N, M, SomeArg, NoArg) , Name (..) , argDef ) where import Control.Lens (Iso', Wrapped(..), iso) import Data.Aeson (FromJSON, ToJSON) import Data.Data (Data) import Fmt (Buildable(..)) import GHC.TypeLits (KnownSymbol, symbolVal) import Named (Name(..), NamedF(..), argDef, (!), (:!), (:?)) import qualified Text.Show import Morley.Util.Label (Label) -- | Convenience pattern synonym, use this instead of 'Named.arg' with @ViewPatterns@. pattern (:!) :: Name name -> a -> NamedF Identity a name pattern (:!) n v <- (decomposeNamedF -> (n, Identity v)) where (:!) _ v = ArgF (Identity v) {-# COMPLETE (:!) #-} -- | Convenience pattern synonym, use this instead of 'Named.argF' with @ViewPatterns@. pattern (:?) :: Name name -> Maybe a -> NamedF Maybe a name pattern (:?) n v <- (decomposeNamedF -> (n, v)) where (:?) _ v = ArgF v {-# COMPLETE (:?) #-} decomposeNamedF :: NamedF f a name -> (Name name, f a) decomposeNamedF (ArgF fa) = (Name, fa) -- | Convenience pattern synonym, use this instead of 'Named.arg' with @ViewPatterns@ -- when the @name@ can be inferred. pattern N :: a -> NamedF Identity a name pattern N a = ArgF (Identity a) {-# COMPLETE N #-} -- | Convenience pattern synonym, use this instead of 'Named.argF' with @ViewPatterns@ -- when the @name@ can be inferred. Matches only on @Just@ values pattern SomeArg :: a -> NamedF Maybe a name pattern SomeArg a = ArgF (Just a) -- | Convenience pattern synonym, use this instead of 'Named.argF' with @ViewPatterns@ -- when the @name@ can be inferred. Matches only on @Nothing@ values pattern NoArg :: NamedF Maybe a name pattern NoArg = ArgF Nothing {-# COMPLETE NoArg, SomeArg #-} -- | Convenience pattern synonym for @NamedF Maybe name a@, use this instead of 'Named.argF' with @ViewPatterns@ -- when the @name@ can be inferred. pattern M :: Maybe a -> NamedF Maybe a name pattern M a = ArgF a {-# COMPLETE M #-} -- | Special version of 'Morley.Util.Named.(:!)' for monadic operations (<:!>) :: Functor m => Name name -> m a -> m (NamedF Identity a name) (<:!>) name = fmap (name :!) infixl 4 <:!> -- | Special version of 'Morley.Util.Named.(:?)' for monadic operations (<:?>) :: Functor m => Name name -> m (Maybe a) -> m (NamedF Maybe a name) (<:?>) name = fmap (name :?) infixl 4 <:?> type family ApplyNamedFunctor (f :: Type -> Type) (a :: Type) where ApplyNamedFunctor Identity a = a ApplyNamedFunctor Maybe a = Maybe a type family NamedInner (n :: 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 instance (NFData (f a)) => NFData (NamedF f a name) where rnf (ArgF a) = rnf 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)