packages feed

disco-0.1.0.0: src/Disco/Effects/Store.hs

{-# LANGUAGE BlockArguments  #-}
{-# LANGUAGE TemplateHaskell #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  Disco.Effects.Store
-- Copyright   :  disco team and contributors
-- Maintainer  :  byorgey@gmail.com
--
-- SPDX-License-Identifier: BSD-3-Clause
--
-- Polysemy effect for a memory store with integer keys.
--
-----------------------------------------------------------------------------

module Disco.Effects.Store where

import qualified Data.IntMap.Lazy      as IntMap
import           Data.IntSet           (IntSet)
import qualified Data.IntSet           as IntSet

import           Disco.Effects.Counter
import           Polysemy
import           Polysemy.State

data Store v m a where

  ClearStore  :: Store v m ()
  New         :: v -> Store v m Int
  LookupStore :: Int -> Store v m (Maybe v)
  InsertStore :: Int -> v -> Store v m ()
  MapStore    :: (v -> v) -> Store v m ()
  AssocsStore :: Store v m [(Int, v)]
  KeepKeys    :: IntSet -> Store v m ()

makeSem ''Store

-- | Dispatch a store effect.
runStore :: forall v r a. Sem (Store v ': r) a -> Sem r a
runStore
  = runCounter
  . evalState @(IntMap.IntMap v) IntMap.empty
  . reinterpret2 \case
      ClearStore      -> put IntMap.empty
      New v           -> do
        loc <- fromIntegral <$> next
        modify $ IntMap.insert loc v
        return loc
      LookupStore k   -> gets (IntMap.lookup k)
      InsertStore k v -> modify (IntMap.insert k v)
      MapStore f      -> modify (IntMap.map f)
      AssocsStore     -> gets IntMap.assocs
      KeepKeys ks     -> modify (\m -> IntMap.withoutKeys m (IntMap.keysSet m `IntSet.difference` ks))