{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Roboservant.Types.Breakdown where
import Data.Dynamic (Dynamic)
import Data.Hashable
import Data.Kind
import Data.List.NonEmpty (NonEmpty (..))
import qualified Data.List.NonEmpty as NEL
import Data.Typeable (Typeable)
import GHC.Generics
import Roboservant.Types.Internal
import Servant
import Roboservant.Types.Orphans()
breakdown ::
(Hashable x, Typeable x, Breakdown x) =>
x ->
NonEmpty (Dynamic, Int)
breakdown :: forall x.
(Hashable x, Typeable x, Breakdown x) =>
x -> NonEmpty (Dynamic, Int)
breakdown x
x = forall a. (Hashable a, Typeable a) => a -> (Dynamic, Int)
hashedDyn x
x forall a. a -> [a] -> NonEmpty a
:| forall x. Breakdown x => x -> [(Dynamic, Int)]
breakdownExtras x
x
class Breakdown x where
:: x -> [(Dynamic, Int)]
instance (Hashable x, Typeable x) => Breakdown (Atom x) where
breakdownExtras :: Atom x -> [(Dynamic, Int)]
breakdownExtras Atom x
_ = []
deriving via (Atom ()) instance Breakdown ()
deriving via (Atom Int) instance Breakdown Int
deriving via (Atom Char) instance Breakdown Char
deriving via (Compound (Maybe x)) instance (Typeable x, Hashable x, Breakdown x) => Breakdown (Maybe x)
instance (Hashable x, Typeable x, Breakdown x) => Breakdown [x] where
breakdownExtras :: [x] -> [(Dynamic, Int)]
breakdownExtras [x]
stash = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (forall a. NonEmpty a -> [a]
NEL.toList forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall x.
(Hashable x, Typeable x, Breakdown x) =>
x -> NonEmpty (Dynamic, Int)
breakdown) [x]
stash
class GBreakdown (f :: k -> Type) where
:: f a -> [(Dynamic, Int)]
instance (Hashable x, Typeable x, Generic x, GBreakdown (Rep x)) => Breakdown (Compound (x :: Type)) where
breakdownExtras :: Compound x -> [(Dynamic, Int)]
breakdownExtras = forall k (f :: k -> *) (a :: k).
GBreakdown f =>
f a -> [(Dynamic, Int)]
gBreakdownExtras forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a x. Generic a => a -> Rep a x
from forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall x. Compound x -> x
unCompound
instance GBreakdown f => GBreakdown (M1 S c f) where
gBreakdownExtras :: forall (a :: k). M1 S c f a -> [(Dynamic, Int)]
gBreakdownExtras (M1 f a
f) = forall k (f :: k -> *) (a :: k).
GBreakdown f =>
f a -> [(Dynamic, Int)]
gBreakdownExtras f a
f
instance GBreakdown b => GBreakdown (M1 D a b) where
gBreakdownExtras :: forall (a :: k). M1 D a b a -> [(Dynamic, Int)]
gBreakdownExtras (M1 b a
f) = forall k (f :: k -> *) (a :: k).
GBreakdown f =>
f a -> [(Dynamic, Int)]
gBreakdownExtras b a
f
instance GBreakdown b => GBreakdown (M1 C a b) where
gBreakdownExtras :: forall (a :: k). M1 C a b a -> [(Dynamic, Int)]
gBreakdownExtras (M1 b a
f) = forall k (f :: k -> *) (a :: k).
GBreakdown f =>
f a -> [(Dynamic, Int)]
gBreakdownExtras b a
f
instance (GBreakdown a, GBreakdown b) => GBreakdown (a :*: b) where
gBreakdownExtras :: forall (a :: k). (:*:) a b a -> [(Dynamic, Int)]
gBreakdownExtras (a a
a :*: b a
b) = forall k (f :: k -> *) (a :: k).
GBreakdown f =>
f a -> [(Dynamic, Int)]
gBreakdownExtras a a
a forall a. Semigroup a => a -> a -> a
<> forall k (f :: k -> *) (a :: k).
GBreakdown f =>
f a -> [(Dynamic, Int)]
gBreakdownExtras b a
b
instance (GBreakdown a, GBreakdown b) => GBreakdown (a :+: b) where
gBreakdownExtras :: forall (a :: k). (:+:) a b a -> [(Dynamic, Int)]
gBreakdownExtras = \case
L1 a a
a -> forall k (f :: k -> *) (a :: k).
GBreakdown f =>
f a -> [(Dynamic, Int)]
gBreakdownExtras a a
a
R1 b a
a -> forall k (f :: k -> *) (a :: k).
GBreakdown f =>
f a -> [(Dynamic, Int)]
gBreakdownExtras b a
a
instance (Hashable a, Typeable a, Breakdown a) => GBreakdown (K1 R a) where
gBreakdownExtras :: forall (a :: k). K1 R a a -> [(Dynamic, Int)]
gBreakdownExtras (K1 a
c) = forall a. NonEmpty a -> [a]
NEL.toList forall a b. (a -> b) -> a -> b
$ forall x.
(Hashable x, Typeable x, Breakdown x) =>
x -> NonEmpty (Dynamic, Int)
breakdown a
c
instance GBreakdown U1 where
gBreakdownExtras :: forall (a :: k). U1 a -> [(Dynamic, Int)]
gBreakdownExtras U1 a
U1 = []
deriving via (Atom NoContent) instance Breakdown NoContent