morley-1.16.0: src/Morley/Util/Named.hs
-- 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)