module Polysemy.State.Keyed
  ( KeyedState(..)
  -- * Operations
  , getAt
  , putAt
  , modifyAt
  , rename
  , zoomAt
  -- * @State@ interpreters
  , runKeyedStates
  , KeyedStore(..)
  , lookupAt, updateAt, updateAtBy
  , runKeyedStateStore, runKeyedStateStoreBy
  -- * @IO@ interpreters
  , Reference, module Data.Constraint.Trivial
  , runKeyedStateRefsIO
  , runKeyedStateVarsIO, runKeyedStateVarsOfIO
  , runStorableKeyedStateVarsIO, runStorableKeyedStateVarsOfIO
  , runConstrainedKeyedStateVarsIO, runConstrainedKeyedStateVarsOfIO
  )
  where

import Data.Constraint
import Data.Constraint.Extras
import Data.Constraint.Trivial
import Data.StateVar hiding (get)
import qualified Data.StateVar as StateVar
import Data.Typeable
import Foreign.Storable
import Polysemy
import Polysemy.Input
import Polysemy.Internal
import Polysemy.Membership
import Polysemy.State

newtype UnconstrainedKey k a = UnconstrainedKey { UnconstrainedKey k a -> k a
getUnconstrainedKey :: k a }
instance ArgDict Unconstrained (UnconstrainedKey k) where
  type ConstraintsFor (UnconstrainedKey k) Unconstrained = ()
  argDict :: UnconstrainedKey k a -> Dict (Unconstrained a)
argDict = Dict (Unconstrained a)
-> UnconstrainedKey k a -> Dict (Unconstrained a)
forall a b. a -> b -> a
const Dict (Unconstrained a)
forall (a :: Constraint). a => Dict a
Dict

{-|
An interpreter for @KeyedState@ may or may not obey the following "consistency" law:

* for any @k@, @k'@, and @v@, @putAt k v *> getAt k' = if k == k' then pure v else getAt k'@

This law is relevant for most pure interpretations of @KeyedState@, but only applies when the values in the state are /disjoint/ (setting at @k@ does not modify the value at @k'@ when @k /= k'@) and /local/ (never modified by another thread or program). Some useful sets of stateful values violate this law: for example, the [@sdl2@](https://hackage.haskell.org/package/sdl2) package provides a set of [@StateVar@s](https://hackage.haskell.org/package/StateVar/docs/Data-StateVar.html#t:StateVar) for each SDL window created, which are neither disjoint nor local.
-}
data KeyedState k :: Effect where
  GetAt :: k a -> KeyedState k m a
  PutAt :: k a -> a -> KeyedState k m ()

makeSem ''KeyedState

modifyAt ::
  forall k a r.
  Member (KeyedState k) r =>
  k a -> (a -> a) -> Sem r ()
modifyAt :: k a -> (a -> a) -> Sem r ()
modifyAt k a
k a -> a
f = k a -> a -> Sem r ()
forall (k :: * -> *) (r :: [Effect]) a.
MemberWithError (KeyedState k) r =>
k a -> a -> Sem r ()
putAt k a
k (a -> Sem r ()) -> (a -> a) -> a -> Sem r ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
f (a -> Sem r ()) -> Sem r a -> Sem r ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< k a -> Sem r a
forall (k :: * -> *) (r :: [Effect]) a.
MemberWithError (KeyedState k) r =>
k a -> Sem r a
getAt k a
k

-- |Run a @KeyedState@ operation in the context of another @KeyedState@ effect by translating the keys.
rename ::
  forall k k' r a.
  Member (KeyedState k') r =>
  (forall x. k x -> k' x) -> Sem (KeyedState k : r) a -> Sem r a
rename :: (forall x. k x -> k' x) -> Sem (KeyedState k : r) a -> Sem r a
rename forall x. k x -> k' x
h =
  (forall (rInitial :: [Effect]) x.
 KeyedState k (Sem rInitial) x -> KeyedState k' (Sem rInitial) x)
-> Sem (KeyedState k : r) a -> Sem r a
forall (e1 :: Effect) (e2 :: Effect) (r :: [Effect]) a.
Member e2 r =>
(forall (rInitial :: [Effect]) x.
 e1 (Sem rInitial) x -> e2 (Sem rInitial) x)
-> Sem (e1 : r) a -> Sem r a
transform ((forall (rInitial :: [Effect]) x.
  KeyedState k (Sem rInitial) x -> KeyedState k' (Sem rInitial) x)
 -> Sem (KeyedState k : r) a -> Sem r a)
-> (forall (rInitial :: [Effect]) x.
    KeyedState k (Sem rInitial) x -> KeyedState k' (Sem rInitial) x)
-> Sem (KeyedState k : r) a
-> Sem r a
forall a b. (a -> b) -> a -> b
$ \case
    GetAt k -> k' x -> KeyedState k' (Sem rInitial) x
forall (k :: * -> *) a (m :: * -> *). k a -> KeyedState k m a
GetAt (k' x -> KeyedState k' (Sem rInitial) x)
-> k' x -> KeyedState k' (Sem rInitial) x
forall a b. (a -> b) -> a -> b
$ k x -> k' x
forall x. k x -> k' x
h k x
k
    PutAt k x -> k' a -> a -> KeyedState k' (Sem rInitial) ()
forall (k :: * -> *) a (m :: * -> *). k a -> a -> KeyedState k m ()
PutAt (k a -> k' a
forall x. k x -> k' x
h k a
k) a
x

-- |Interpret a @State@ effect as a single variable in a @KeyedState@ effect.
zoomAt ::
  forall k a r.
  Member (KeyedState k) r =>
  k a -> InterpreterFor (State a) r
zoomAt :: k a -> InterpreterFor (State a) r
zoomAt k a
k =
  (forall x (rInitial :: [Effect]).
 State a (Sem rInitial) x -> Sem r x)
-> Sem (State a : r) a -> Sem r a
forall (e :: Effect) (r :: [Effect]) a.
FirstOrder e "interpret" =>
(forall x (rInitial :: [Effect]). e (Sem rInitial) x -> Sem r x)
-> Sem (e : r) a -> Sem r a
interpret ((forall x (rInitial :: [Effect]).
  State a (Sem rInitial) x -> Sem r x)
 -> Sem (State a : r) a -> Sem r a)
-> (forall x (rInitial :: [Effect]).
    State a (Sem rInitial) x -> Sem r x)
-> Sem (State a : r) a
-> Sem r a
forall a b. (a -> b) -> a -> b
$ \case
    State a (Sem rInitial) x
Get -> k a -> Sem r a
forall (k :: * -> *) (r :: [Effect]) a.
MemberWithError (KeyedState k) r =>
k a -> Sem r a
getAt k a
k
    Put x -> k a -> a -> Sem r ()
forall (k :: * -> *) (r :: [Effect]) a.
MemberWithError (KeyedState k) r =>
k a -> a -> Sem r ()
putAt k a
k a
x

{-|
Distribute a @KeyedState@ effect across multiple @State@ effects by mapping each key to an effect.

Lawful if the @State@ effects are interpreted lawfully.
-}
runKeyedStates ::
  forall k r.
  (forall a. k a -> ElemOf (State a) r) ->
  InterpreterFor (KeyedState k) r
runKeyedStates :: (forall a. k a -> ElemOf (State a) r)
-> InterpreterFor (KeyedState k) r
runKeyedStates forall a. k a -> ElemOf (State a) r
h =
  (forall x (rInitial :: [Effect]).
 KeyedState k (Sem rInitial) x -> Sem r x)
-> Sem (KeyedState k : r) a -> Sem r a
forall (e :: Effect) (r :: [Effect]) a.
FirstOrder e "interpret" =>
(forall x (rInitial :: [Effect]). e (Sem rInitial) x -> Sem r x)
-> Sem (e : r) a -> Sem r a
interpret ((forall x (rInitial :: [Effect]).
  KeyedState k (Sem rInitial) x -> Sem r x)
 -> Sem (KeyedState k : r) a -> Sem r a)
-> (forall x (rInitial :: [Effect]).
    KeyedState k (Sem rInitial) x -> Sem r x)
-> Sem (KeyedState k : r) a
-> Sem r a
forall a b. (a -> b) -> a -> b
$ \case
    GetAt k -> ElemOf (State x) r -> Sem (State x : r) x -> Sem r x
forall (e :: Effect) (r :: [Effect]) a.
ElemOf e r -> Sem (e : r) a -> Sem r a
subsumeUsing (k x -> ElemOf (State x) r
forall a. k a -> ElemOf (State a) r
h k x
k) Sem (State x : r) x
forall s (r :: [Effect]). MemberWithError (State s) r => Sem r s
get
    PutAt k x -> ElemOf (State a) r -> Sem (State a : r) () -> Sem r ()
forall (e :: Effect) (r :: [Effect]) a.
ElemOf e r -> Sem (e : r) a -> Sem r a
subsumeUsing (k a -> ElemOf (State a) r
forall a. k a -> ElemOf (State a) r
h k a
k) (Sem (State a : r) () -> Sem r ())
-> Sem (State a : r) () -> Sem r ()
forall a b. (a -> b) -> a -> b
$ a -> Sem (State a : r) ()
forall s (r :: [Effect]).
MemberWithError (State s) r =>
s -> Sem r ()
put a
x

-- |A @KeyedStore k@ is a total map over keys of type @k@.
newtype KeyedStore k = KeyedStore { KeyedStore k -> forall a. k a -> a
runKeyedStore :: forall a. k a -> a }

-- |Retrieve a value from a @KeyedStore@.
lookupAt :: k a -> KeyedStore k -> a
lookupAt :: k a -> KeyedStore k -> a
lookupAt = (KeyedStore k -> k a -> a) -> k a -> KeyedStore k -> a
forall a b c. (a -> b -> c) -> b -> a -> c
flip KeyedStore k -> k a -> a
forall (k :: * -> *). KeyedStore k -> forall a. k a -> a
runKeyedStore

-- |Update a value in a @KeyedStore@, using @Typeable@ instances to check for key type equality.
updateAt ::
  forall k a.
  (Typeable a, Has Typeable k, forall x. Eq (k x)) =>
  k a -> a -> KeyedStore k -> KeyedStore k
updateAt :: k a -> a -> KeyedStore k -> KeyedStore k
updateAt = (forall b. k a -> k b -> Maybe (a :~: b))
-> k a -> a -> KeyedStore k -> KeyedStore k
forall (k :: * -> *) a.
(forall x. Eq (k x)) =>
(forall b. k a -> k b -> Maybe (a :~: b))
-> k a -> a -> KeyedStore k -> KeyedStore k
updateAtBy ((forall b. k a -> k b -> Maybe (a :~: b))
 -> k a -> a -> KeyedStore k -> KeyedStore k)
-> (forall b. k a -> k b -> Maybe (a :~: b))
-> k a
-> a
-> KeyedStore k
-> KeyedStore k
forall a b. (a -> b) -> a -> b
$ \k a
_ k b
k' -> k b -> (Typeable b => Maybe (a :~: b)) -> Maybe (a :~: b)
forall k (c :: k -> Constraint) (f :: k -> *) (a :: k) r.
Has c f =>
f a -> (c a => r) -> r
has @Typeable k b
k' Typeable b => Maybe (a :~: b)
forall k (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT

-- |Update an entry in a @KeyedStore@, using a specified function to check for key type equality. This can be used with functions like [@testEquality@](https://hackage.haskell.org/package/base/docs/Data-Type-Equality.html#v:testEquality) and [@geq@](https://hackage.haskell.org/package/some/docs/Data-GADT-Compare.html#v:geq) to avoid @Typeable@ constraints.
updateAtBy ::
  forall k a.
  (forall x. Eq (k x)) =>
  (forall b. k a -> k b -> Maybe (a :~: b)) ->
  k a -> a -> KeyedStore k -> KeyedStore k
updateAtBy :: (forall b. k a -> k b -> Maybe (a :~: b))
-> k a -> a -> KeyedStore k -> KeyedStore k
updateAtBy forall b. k a -> k b -> Maybe (a :~: b)
eq k a
k a
x KeyedStore k
m =
  (forall a. k a -> a) -> KeyedStore k
forall (k :: * -> *). (forall a. k a -> a) -> KeyedStore k
KeyedStore ((forall a. k a -> a) -> KeyedStore k)
-> (forall a. k a -> a) -> KeyedStore k
forall a b. (a -> b) -> a -> b
$ \k a
k' ->
    case k a -> k a -> Maybe (a :~: a)
forall b. k a -> k b -> Maybe (a :~: b)
eq k a
k k a
k' of
      Just a :~: a
Refl | k a
k k a -> k a -> Bool
forall a. Eq a => a -> a -> Bool
== k a
k a
k' -> a
a
x
      Maybe (a :~: a)
_ -> k a -> KeyedStore k -> a
forall (k :: * -> *) a. k a -> KeyedStore k -> a
lookupAt k a
k' KeyedStore k
m

{-|
Interpret a @KeyedState@ effect as a @State@ effect over a @KeyedStore@, using @Typeable@ instances to check for key type equality.

Lawful.
-}
runKeyedStateStore ::
  forall k r.
  (Member (State (KeyedStore k)) r, forall a. Eq (k a), Has Typeable k) =>
  InterpreterFor (KeyedState k) r
runKeyedStateStore :: InterpreterFor (KeyedState k) r
runKeyedStateStore =
  (forall a b. k a -> k b -> Maybe (a :~: b))
-> InterpreterFor (KeyedState k) r
forall (k :: * -> *) (r :: [Effect]).
(Member (State (KeyedStore k)) r, forall a. Eq (k a)) =>
(forall a b. k a -> k b -> Maybe (a :~: b))
-> InterpreterFor (KeyedState k) r
runKeyedStateStoreBy ((forall a b. k a -> k b -> Maybe (a :~: b))
 -> InterpreterFor (KeyedState k) r)
-> (forall a b. k a -> k b -> Maybe (a :~: b))
-> InterpreterFor (KeyedState k) r
forall a b. (a -> b) -> a -> b
$ \k a
k k b
k' ->
    k a -> (Typeable a => Maybe (a :~: b)) -> Maybe (a :~: b)
forall k (c :: k -> Constraint) (f :: k -> *) (a :: k) r.
Has c f =>
f a -> (c a => r) -> r
has @Typeable k a
k ((Typeable a => Maybe (a :~: b)) -> Maybe (a :~: b))
-> (Typeable a => Maybe (a :~: b)) -> Maybe (a :~: b)
forall a b. (a -> b) -> a -> b
$ k b -> (Typeable b => Maybe (a :~: b)) -> Maybe (a :~: b)
forall k (c :: k -> Constraint) (f :: k -> *) (a :: k) r.
Has c f =>
f a -> (c a => r) -> r
has @Typeable k b
k' Typeable b => Maybe (a :~: b)
forall k (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT

{-|
Interpret a @KeyedState@ effect as a @State@ effect over a @KeyedStore@, using a specified function to check for key type equality. This can be used with functions like [@testEquality@](https://hackage.haskell.org/package/base/docs/Data-Type-Equality.html#v:testEquality) and [@geq@](https://hackage.haskell.org/package/some/docs/Data-GADT-Compare.html#v:geq) to avoid @Typeable@ constraints.

Lawful if the key type equality function always returns @Just Refl@ whenever possible (i.e. it correctly says that any two equal types are equal); otherwise, @putAt@ may silently fail to have any effect in some cases.
-}
runKeyedStateStoreBy ::
  forall k r.
  (Member (State (KeyedStore k)) r, forall a. Eq (k a)) =>
  (forall a b. k a -> k b -> Maybe (a :~: b)) ->
  InterpreterFor (KeyedState k) r
runKeyedStateStoreBy :: (forall a b. k a -> k b -> Maybe (a :~: b))
-> InterpreterFor (KeyedState k) r
runKeyedStateStoreBy forall a b. k a -> k b -> Maybe (a :~: b)
eq =
  (forall x (rInitial :: [Effect]).
 KeyedState k (Sem rInitial) x -> Sem r x)
-> Sem (KeyedState k : r) a -> Sem r a
forall (e :: Effect) (r :: [Effect]) a.
FirstOrder e "interpret" =>
(forall x (rInitial :: [Effect]). e (Sem rInitial) x -> Sem r x)
-> Sem (e : r) a -> Sem r a
interpret ((forall x (rInitial :: [Effect]).
  KeyedState k (Sem rInitial) x -> Sem r x)
 -> Sem (KeyedState k : r) a -> Sem r a)
-> (forall x (rInitial :: [Effect]).
    KeyedState k (Sem rInitial) x -> Sem r x)
-> Sem (KeyedState k : r) a
-> Sem r a
forall a b. (a -> b) -> a -> b
$ \case
    GetAt k -> k x -> KeyedStore k -> x
forall (k :: * -> *) a. k a -> KeyedStore k -> a
lookupAt k x
k (KeyedStore k -> x) -> Sem r (KeyedStore k) -> Sem r x
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Sem r (KeyedStore k)
forall s (r :: [Effect]). MemberWithError (State s) r => Sem r s
get
    PutAt k x -> KeyedStore k -> Sem r ()
forall s (r :: [Effect]).
MemberWithError (State s) r =>
s -> Sem r ()
put (KeyedStore k -> Sem r ())
-> (KeyedStore k -> KeyedStore k) -> KeyedStore k -> Sem r ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall b. k a -> k b -> Maybe (a :~: b))
-> k a -> a -> KeyedStore k -> KeyedStore k
forall (k :: * -> *) a.
(forall x. Eq (k x)) =>
(forall b. k a -> k b -> Maybe (a :~: b))
-> k a -> a -> KeyedStore k -> KeyedStore k
updateAtBy forall b. k a -> k b -> Maybe (a :~: b)
forall a b. k a -> k b -> Maybe (a :~: b)
eq k a
k a
x (KeyedStore k -> Sem r ()) -> Sem r (KeyedStore k) -> Sem r ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Sem r (KeyedStore k)
forall s (r :: [Effect]). MemberWithError (State s) r => Sem r s
get

-- |An instance of @Reference c k@ indicates that @k@ is an @IO@ reference type (like @IORef@, @STRef@, ...) that requires values to meet the constraint @c@. For more information, see the documentation for @HasGetter@ and @HasSetter@.
class (forall a. c a => HasGetter (k a) a, forall a. c a => HasSetter (k a) a) => Reference c k
instance (forall a. c a => HasGetter (k a) a, forall a. c a => HasSetter (k a) a) => Reference c k

{-|
Interpret each key directly as an @IO@ reference. Useful with "key" types like @IORef@ and @STRef@.
 
Note that there is no way to directly interpret a @KeyedState@ effect where the "keys" are references that require @Storable@ or other constraints to modify, like @Ptr@ and @ForeignPtr@, since @PutAt@ does not have any constraints on its argument type. To use @KeyedState@ with constrained reference types, you can define a GADT key type to represent the set of references and interpret the effect with [@runStorableKeyedStateVarsIO@](#v:runStorableKeyedStateVarsIO), [@runStorableKeyedStateVarsOfIO@](#v:runStorableKeyedStateVarsOfIO), [@runConstrainedKeyedStateVarsIO@](#v:runConstrainedKeyedStateVarsIO), or [@runConstrainedKeyedStateVarsOfIO@](#v:runConstrainedKeyedStateVarsOfIO).

Lawful if all references used with @getAt@ and @putAt@ are disjoint and local.
-}
runKeyedStateRefsIO ::
  forall k r.
  (Member (Embed IO) r, Reference Unconstrained k) =>
  InterpreterFor (KeyedState k) r
runKeyedStateRefsIO :: InterpreterFor (KeyedState k) r
runKeyedStateRefsIO = (forall a. k a -> k a) -> InterpreterFor (KeyedState k) r
forall (ref :: * -> *) (k :: * -> *) (r :: [Effect]).
(Member (Embed IO) r, Reference Unconstrained ref) =>
(forall a. k a -> ref a) -> InterpreterFor (KeyedState k) r
runKeyedStateVarsIO forall a. a -> a
forall a. k a -> k a
id

{-|
Interpret a @KeyedState@ effect as a set of @IO@ references by mapping each key to a reference.

Lawful if all references returned by the mapping are disjoint and local.
-}
runKeyedStateVarsIO ::
  forall ref k r.
  (Member (Embed IO) r, Reference Unconstrained ref) =>
  (forall a. k a -> ref a) ->
  InterpreterFor (KeyedState k) r
runKeyedStateVarsIO :: (forall a. k a -> ref a) -> InterpreterFor (KeyedState k) r
runKeyedStateVarsIO forall a. k a -> ref a
h =
  () -> Sem (Input () : r) a -> Sem r a
forall i (r :: [Effect]) a. i -> Sem (Input i : r) a -> Sem r a
runInputConst () (Sem (Input () : r) a -> Sem r a)
-> (Sem (KeyedState k : r) a -> Sem (Input () : r) a)
-> Sem (KeyedState k : r) a
-> Sem r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  (forall a. k a -> () -> ref a)
-> InterpreterFor (KeyedState k) (Input () : r)
forall s (ref :: * -> *) (k :: * -> *) (r :: [Effect]).
(Members '[Input s, Embed IO] r, Reference Unconstrained ref) =>
(forall a. k a -> s -> ref a) -> InterpreterFor (KeyedState k) r
runKeyedStateVarsOfIO @() (\k a
k ()
_ -> k a -> ref a
forall a. k a -> ref a
h k a
k) (Sem (KeyedState k : Input () : r) a -> Sem (Input () : r) a)
-> (Sem (KeyedState k : r) a
    -> Sem (KeyedState k : Input () : r) a)
-> Sem (KeyedState k : r) a
-> Sem (Input () : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem (KeyedState k : r) a -> Sem (KeyedState k : Input () : r) a
forall (e2 :: Effect) (e1 :: Effect) (r :: [Effect]) a.
Sem (e1 : r) a -> Sem (e1 : e2 : r) a
raiseUnder

{-|
Like [@runKeyedStateVarsIO@](#v:runKeyedStateVarsIO), but for references that are accessed through some pure handle, like the [window attributes](https://hackage.haskell.org/package/sdl2/docs/SDL-Video.html#g:3) in [@sdl2@](https://hackage.haskell.org/package/sdl2) package.

Lawful if all references returned by the mapping are disjoint and local.
-}
runKeyedStateVarsOfIO ::
  forall s ref k r.
  (Members [Input s, Embed IO] r, Reference Unconstrained ref) =>
  (forall a. k a -> s -> ref a) ->
  InterpreterFor (KeyedState k) r
runKeyedStateVarsOfIO :: (forall a. k a -> s -> ref a) -> InterpreterFor (KeyedState k) r
runKeyedStateVarsOfIO forall a. k a -> s -> ref a
h =
  (forall a. UnconstrainedKey k a -> s -> ref a)
-> InterpreterFor (KeyedState (UnconstrainedKey k)) r
forall s (c :: * -> Constraint) (ref :: * -> *) (k :: * -> *)
       (r :: [Effect]).
(Members '[Input s, Embed IO] r, Reference c ref, Has c k) =>
(forall a. k a -> s -> ref a) -> InterpreterFor (KeyedState k) r
runConstrainedKeyedStateVarsOfIO @s @Unconstrained (k a -> s -> ref a
forall a. k a -> s -> ref a
h (k a -> s -> ref a)
-> (UnconstrainedKey k a -> k a)
-> UnconstrainedKey k a
-> s
-> ref a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnconstrainedKey k a -> k a
forall (k :: * -> *) a. UnconstrainedKey k a -> k a
getUnconstrainedKey) (Sem (KeyedState (UnconstrainedKey k) : r) a -> Sem r a)
-> (Sem (KeyedState k : r) a
    -> Sem (KeyedState (UnconstrainedKey k) : r) a)
-> Sem (KeyedState k : r) a
-> Sem r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  (forall x. k x -> UnconstrainedKey k x)
-> Sem (KeyedState k : KeyedState (UnconstrainedKey k) : r) a
-> Sem (KeyedState (UnconstrainedKey k) : r) a
forall (k :: * -> *) (k' :: * -> *) (r :: [Effect]) a.
Member (KeyedState k') r =>
(forall x. k x -> k' x) -> Sem (KeyedState k : r) a -> Sem r a
rename forall x. k x -> UnconstrainedKey k x
forall (k :: * -> *) a. k a -> UnconstrainedKey k a
UnconstrainedKey (Sem (KeyedState k : KeyedState (UnconstrainedKey k) : r) a
 -> Sem (KeyedState (UnconstrainedKey k) : r) a)
-> (Sem (KeyedState k : r) a
    -> Sem (KeyedState k : KeyedState (UnconstrainedKey k) : r) a)
-> Sem (KeyedState k : r) a
-> Sem (KeyedState (UnconstrainedKey k) : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem (KeyedState k : r) a
-> Sem (KeyedState k : KeyedState (UnconstrainedKey k) : r) a
forall (e2 :: Effect) (e1 :: Effect) (r :: [Effect]) a.
Sem (e1 : r) a -> Sem (e1 : e2 : r) a
raiseUnder

{-|
Interpret a @KeyedState@ effect as a set of @IO@ references by mapping each key to a reference that requires a @Storable@ constraint on values.

Lawful if all references returned by the mapping are disjoint and local.
-}
runStorableKeyedStateVarsIO ::
  forall ref k r.
  (Member (Embed IO) r, Reference Storable ref, Has Storable k) =>
  (forall a. k a -> ref a) ->
  InterpreterFor (KeyedState k) r
runStorableKeyedStateVarsIO :: (forall a. k a -> ref a) -> InterpreterFor (KeyedState k) r
runStorableKeyedStateVarsIO = forall (ref :: * -> *) (k :: * -> *) (r :: [Effect]).
(Member (Embed IO) r, Reference Storable ref, Has Storable k) =>
(forall a. k a -> ref a) -> InterpreterFor (KeyedState k) r
forall (c :: * -> Constraint) (ref :: * -> *) (k :: * -> *)
       (r :: [Effect]).
(Member (Embed IO) r, Reference c ref, Has c k) =>
(forall a. k a -> ref a) -> InterpreterFor (KeyedState k) r
runConstrainedKeyedStateVarsIO @Storable

{-|
Like [@runStorableKeyedStateVarsIO@](#v:runStorableKeyedStateVarsIO), but for references that are accessed through some pure handle.

Lawful if all references returned by the mapping are disjoint and local.
-}
runStorableKeyedStateVarsOfIO ::
  forall s ref k r.
  (Members [Input s, Embed IO] r, Reference Storable ref, Has Storable k) =>
  (forall a. k a -> s -> ref a) ->
  InterpreterFor (KeyedState k) r
runStorableKeyedStateVarsOfIO :: (forall a. k a -> s -> ref a) -> InterpreterFor (KeyedState k) r
runStorableKeyedStateVarsOfIO = forall s (c :: * -> Constraint) (ref :: * -> *) (k :: * -> *)
       (r :: [Effect]).
(Members '[Input s, Embed IO] r, Reference c ref, Has c k) =>
(forall a. k a -> s -> ref a) -> InterpreterFor (KeyedState k) r
forall (ref :: * -> *) (k :: * -> *) (r :: [Effect]).
(Members '[Input s, Embed IO] r, Reference Storable ref,
 Has Storable k) =>
(forall a. k a -> s -> ref a) -> InterpreterFor (KeyedState k) r
runConstrainedKeyedStateVarsOfIO @s @Storable

{-|
Interpret a @KeyedState effect as a set of @IO@ references by mapping each key to a references that requires some specified constraint on values. This will usually need the @TypeApplications@ extension to disambiguate the constraint. This can be used if you have some exotic reference type that requires a constraint other than @Storable@.

Lawful if all references returned by the mapping are disjoint and local.
-}
runConstrainedKeyedStateVarsIO ::
  forall c ref k r.
  (Member (Embed IO) r, Reference c ref, Has c k) =>
  (forall a. k a -> ref a) ->
  InterpreterFor (KeyedState k) r
runConstrainedKeyedStateVarsIO :: (forall a. k a -> ref a) -> InterpreterFor (KeyedState k) r
runConstrainedKeyedStateVarsIO forall a. k a -> ref a
h =
  () -> Sem (Input () : r) a -> Sem r a
forall i (r :: [Effect]) a. i -> Sem (Input i : r) a -> Sem r a
runInputConst () (Sem (Input () : r) a -> Sem r a)
-> (Sem (KeyedState k : r) a -> Sem (Input () : r) a)
-> Sem (KeyedState k : r) a
-> Sem r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  (forall a. k a -> () -> ref a)
-> InterpreterFor (KeyedState k) (Input () : r)
forall s (c :: * -> Constraint) (ref :: * -> *) (k :: * -> *)
       (r :: [Effect]).
(Members '[Input s, Embed IO] r, Reference c ref, Has c k) =>
(forall a. k a -> s -> ref a) -> InterpreterFor (KeyedState k) r
runConstrainedKeyedStateVarsOfIO @() @c (\k a
k ()
_ -> k a -> ref a
forall a. k a -> ref a
h k a
k) (Sem (KeyedState k : Input () : r) a -> Sem (Input () : r) a)
-> (Sem (KeyedState k : r) a
    -> Sem (KeyedState k : Input () : r) a)
-> Sem (KeyedState k : r) a
-> Sem (Input () : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  Sem (KeyedState k : r) a -> Sem (KeyedState k : Input () : r) a
forall (e2 :: Effect) (e1 :: Effect) (r :: [Effect]) a.
Sem (e1 : r) a -> Sem (e1 : e2 : r) a
raiseUnder

{-|
Like [@runConstrainedKeyedStateVarsIO@](#v:runConstrainedKeyedStateVarsIO), but for references that are accessed through some pure handle.

Lawful if all references returned by the mapping are disjoint and local.
-}
runConstrainedKeyedStateVarsOfIO ::
  forall s c ref k r.
  (Members [Input s, Embed IO] r, Reference c ref, Has c k) =>
  (forall a. k a -> s -> ref a) ->
  InterpreterFor (KeyedState k) r
runConstrainedKeyedStateVarsOfIO :: (forall a. k a -> s -> ref a) -> InterpreterFor (KeyedState k) r
runConstrainedKeyedStateVarsOfIO forall a. k a -> s -> ref a
h =
  (forall x (rInitial :: [Effect]).
 KeyedState k (Sem rInitial) x -> Sem r x)
-> Sem (KeyedState k : r) a -> Sem r a
forall (e :: Effect) (r :: [Effect]) a.
FirstOrder e "interpret" =>
(forall x (rInitial :: [Effect]). e (Sem rInitial) x -> Sem r x)
-> Sem (e : r) a -> Sem r a
interpret ((forall x (rInitial :: [Effect]).
  KeyedState k (Sem rInitial) x -> Sem r x)
 -> Sem (KeyedState k : r) a -> Sem r a)
-> (forall x (rInitial :: [Effect]).
    KeyedState k (Sem rInitial) x -> Sem r x)
-> Sem (KeyedState k : r) a
-> Sem r a
forall a b. (a -> b) -> a -> b
$ \case
    GetAt k -> k x -> (c x => Sem r x) -> Sem r x
forall k (c :: k -> Constraint) (f :: k -> *) (a :: k) r.
Has c f =>
f a -> (c a => r) -> r
has @c k x
k ((c x => Sem r x) -> Sem r x) -> (c x => Sem r x) -> Sem r x
forall a b. (a -> b) -> a -> b
$ Sem r s
forall i (r :: [Effect]). MemberWithError (Input i) r => Sem r i
input Sem r s -> (s -> Sem r x) -> Sem r x
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ref x -> Sem r x
forall t a (m :: * -> *). (HasGetter t a, MonadIO m) => t -> m a
StateVar.get (ref x -> Sem r x) -> (s -> ref x) -> s -> Sem r x
forall b c a. (b -> c) -> (a -> b) -> a -> c
. k x -> s -> ref x
forall a. k a -> s -> ref a
h k x
k
    PutAt k x -> k a -> (c a => Sem r x) -> Sem r x
forall k (c :: k -> Constraint) (f :: k -> *) (a :: k) r.
Has c f =>
f a -> (c a => r) -> r
has @c k a
k ((c a => Sem r x) -> Sem r x) -> (c a => Sem r x) -> Sem r x
forall a b. (a -> b) -> a -> b
$ Sem r s
forall i (r :: [Effect]). MemberWithError (Input i) r => Sem r i
input Sem r s -> (s -> Sem r ()) -> Sem r ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \s
s -> k a -> s -> ref a
forall a. k a -> s -> ref a
h k a
k s
s ref a -> a -> Sem r ()
forall t a (m :: * -> *).
(HasSetter t a, MonadIO m) =>
t -> a -> m ()
$= a
x