module AOC.Util.DynoMap (
    DynoMap(..)
  , lookupDyno
  , lookupDynoWith
  ) where

import           Control.Monad
import           Data.Dynamic
import           Data.Map      (Map)
import           Data.Maybe
import qualified Data.Map      as M

newtype DynoMap = Dyno { DynoMap -> Map String Dynamic
runDyno :: Map String Dynamic }
  deriving newtype (NonEmpty DynoMap -> DynoMap
DynoMap -> DynoMap -> DynoMap
(DynoMap -> DynoMap -> DynoMap)
-> (NonEmpty DynoMap -> DynoMap)
-> (forall b. Integral b => b -> DynoMap -> DynoMap)
-> Semigroup DynoMap
forall b. Integral b => b -> DynoMap -> DynoMap
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: forall b. Integral b => b -> DynoMap -> DynoMap
$cstimes :: forall b. Integral b => b -> DynoMap -> DynoMap
sconcat :: NonEmpty DynoMap -> DynoMap
$csconcat :: NonEmpty DynoMap -> DynoMap
<> :: DynoMap -> DynoMap -> DynoMap
$c<> :: DynoMap -> DynoMap -> DynoMap
Semigroup, Semigroup DynoMap
DynoMap
Semigroup DynoMap
-> DynoMap
-> (DynoMap -> DynoMap -> DynoMap)
-> ([DynoMap] -> DynoMap)
-> Monoid DynoMap
[DynoMap] -> DynoMap
DynoMap -> DynoMap -> DynoMap
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
mconcat :: [DynoMap] -> DynoMap
$cmconcat :: [DynoMap] -> DynoMap
mappend :: DynoMap -> DynoMap -> DynoMap
$cmappend :: DynoMap -> DynoMap -> DynoMap
mempty :: DynoMap
$cmempty :: DynoMap
Monoid)

-- | Lookup the value at a given key in a 'Dyno'.
--
-- > lookupDyno "hello"
lookupDyno
    :: forall a. Typeable a
    => String
    -> DynoMap
    -> Maybe a
lookupDyno :: forall a. Typeable a => String -> DynoMap -> Maybe a
lookupDyno String
sym = Dynamic -> Maybe a
forall a. Typeable a => Dynamic -> Maybe a
fromDynamic
             (Dynamic -> Maybe a)
-> (DynoMap -> Maybe Dynamic) -> DynoMap -> Maybe a
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< String -> Map String Dynamic -> Maybe Dynamic
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup String
sym
               (Map String Dynamic -> Maybe Dynamic)
-> (DynoMap -> Map String Dynamic) -> DynoMap -> Maybe Dynamic
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DynoMap -> Map String Dynamic
runDyno

-- | Like 'lookupDyno', but with a default value to be returned if the key
-- is not found or has the wrong type.
lookupDynoWith
    :: forall a. (Typeable a)
    => String
    -> a
    -> DynoMap
    -> a
lookupDynoWith :: forall a. Typeable a => String -> a -> DynoMap -> a
lookupDynoWith String
sym a
def = a -> Maybe a -> a
forall a. a -> Maybe a -> a
fromMaybe a
def (Maybe a -> a) -> (DynoMap -> Maybe a) -> DynoMap -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> DynoMap -> Maybe a
forall a. Typeable a => String -> DynoMap -> Maybe a
lookupDyno String
sym