packages feed

roboservant-0.1.0.3: src/Roboservant/Types/Internal.hs

{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Roboservant.Types.Internal where

import qualified Data.Dependent.Map as DM
import Data.Dependent.Map (DMap)
import Data.Dependent.Sum
import Data.Dynamic (Dynamic, toDyn)
import Data.Hashable (Hashable, hash)
import Data.IntSet (IntSet)
import Data.List.NonEmpty (NonEmpty (..))
import qualified Data.Map.Strict as Map
import Data.Typeable (Typeable)
import GHC.Generics (Generic)
import qualified Type.Reflection as R

data Provenance
  = Provenance R.SomeTypeRep Int
  deriving (Show, Eq, Generic)

instance Hashable Provenance

data StashValue a
  = StashValue
      { getStashValue :: NonEmpty ([Provenance], a),
        stashHash :: IntSet
      }
  deriving (Functor, Show)

-- wrap in newtype to give a custom Show instance, since the normal
-- instance for DMap is not happy since StashValue needs Show a to show
newtype Stash = Stash {getStash :: DMap R.TypeRep StashValue}
  deriving (Semigroup, Monoid)

instance Show Stash where
  showsPrec i (Stash x) =
    showsPrec i
      $ Map.fromList . map (\(tr :=> StashValue vs _) -> (R.SomeTypeRep tr, fmap fst vs))
      $ DM.toList x

-- | Can't be built up from parts, can't be broken down further.
newtype Atom x = Atom {unAtom :: x}
  deriving newtype (Hashable, Typeable,Eq)

-- | can be broken down and built up from generic pieces
newtype Compound x = Compound {unCompound :: x}
  deriving newtype (Hashable, Typeable, Eq)

hashedDyn :: (Hashable a, Typeable a) => a -> (Dynamic, Int)
hashedDyn a = (toDyn a, hash a)