{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeInType #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_HADDOCK hide #-}
module Capability.State.Internal.Class
( HasState(..)
, get
, put
, state
, modify
, modify'
, gets
, zoom
, Reified (..)
) where
import Capability.Constraints
import Capability.Derive (derive)
import Capability.Reflection
import Capability.Source.Internal.Class
import Capability.Sink.Internal.Class
import Data.Coerce (Coercible, coerce)
import Data.Kind (Type)
import GHC.Exts (Proxy#, proxy#)
class (Monad m, HasSource tag s m, HasSink tag s m)
=> HasState (tag :: k) (s :: Type) (m :: Type -> Type) | tag m -> s
where
state_ :: Proxy# tag -> (s -> (a, s)) -> m a
get :: forall tag s m. HasState tag s m => m s
get :: m s
get = forall k (tag :: k) a (m :: * -> *). HasSource tag a m => m a
forall a (m :: * -> *). HasSource tag a m => m a
await @tag
{-# INLINE get #-}
put :: forall tag s m. HasState tag s m => s -> m ()
put :: s -> m ()
put = forall k (tag :: k) a (m :: * -> *). HasSink tag a m => a -> m ()
forall a (m :: * -> *). HasSink tag a m => a -> m ()
yield @tag
{-# INLINE put #-}
state :: forall tag s m a. HasState tag s m => (s -> (a, s)) -> m a
state :: (s -> (a, s)) -> m a
state = Proxy# tag -> (s -> (a, s)) -> m a
forall k (tag :: k) s (m :: * -> *) a.
HasState tag s m =>
Proxy# tag -> (s -> (a, s)) -> m a
state_ (Proxy# tag
forall k (a :: k). Proxy# a
proxy# @tag)
{-# INLINE state #-}
modify :: forall tag s m. HasState tag s m => (s -> s) -> m ()
modify :: (s -> s) -> m ()
modify s -> s
f = forall k (tag :: k) s (m :: * -> *) a.
HasState tag s m =>
(s -> (a, s)) -> m a
forall s (m :: * -> *) a. HasState tag s m => (s -> (a, s)) -> m a
state @tag ((s -> ((), s)) -> m ()) -> (s -> ((), s)) -> m ()
forall a b. (a -> b) -> a -> b
$ \s
s -> ((), s -> s
f s
s)
{-# INLINE modify #-}
modify' :: forall tag s m. HasState tag s m => (s -> s) -> m ()
modify' :: (s -> s) -> m ()
modify' s -> s
f = do
s
s' <- forall k (tag :: k) s (m :: * -> *). HasState tag s m => m s
forall s (m :: * -> *). HasState tag s m => m s
get @tag
forall k (tag :: k) s (m :: * -> *). HasState tag s m => s -> m ()
forall s (m :: * -> *). HasState tag s m => s -> m ()
put @tag (s -> m ()) -> s -> m ()
forall a b. (a -> b) -> a -> b
$! s -> s
f s
s'
{-# INLINE modify' #-}
gets :: forall tag s m a. HasState tag s m => (s -> a) -> m a
gets :: (s -> a) -> m a
gets s -> a
f = do
s
s <- forall k (tag :: k) s (m :: * -> *). HasState tag s m => m s
forall s (m :: * -> *). HasState tag s m => m s
get @tag
a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (s -> a
f s
s)
{-# INLINE gets #-}
zoom :: forall innertag t (cs :: [Capability]) inner m a.
( forall x. Coercible (t m x) (m x)
, HasState innertag inner (t m)
, All cs m )
=> (forall m'. All (HasState innertag inner ': cs) m' => m' a) -> m a
zoom :: (forall (m' :: * -> *).
All (HasState innertag inner : cs) m' =>
m' a)
-> m a
zoom =
forall (m :: * -> *) a.
(forall x. Coercible (t m x) (m x),
All '[HasState innertag inner] (t m), All cs m) =>
(forall (m' :: * -> *).
(All '[HasState innertag inner] m', All cs m') =>
m' a)
-> m a
forall (t :: (* -> *) -> * -> *)
(derived :: [(* -> *) -> Constraint])
(ambient :: [(* -> *) -> Constraint]) (m :: * -> *) a.
(forall x. Coercible (t m x) (m x), All derived (t m),
All ambient m) =>
(forall (m' :: * -> *). (All derived m', All ambient m') => m' a)
-> m a
derive @t @'[HasState innertag inner] @cs
{-# INLINE zoom #-}
data instance Reified tag (HasState tag s) m = ReifiedState
{ Reified tag (HasState tag s) m -> Reified tag (HasSource tag s) m
_stateSource :: Reified tag (HasSource tag s) m,
Reified tag (HasState tag s) m -> Reified tag (HasSink tag s) m
_stateSink :: Reified tag (HasSink tag s) m,
Reified tag (HasState tag s) m -> forall a. (s -> (a, s)) -> m a
_state :: forall a. (s -> (a, s)) -> m a
}
instance
( Monad m,
Reifies s' (Reified tag (HasState tag s) m)
) =>
HasSource tag s (Reflected s' (HasState tag s) m)
where
await_ :: Proxy# tag -> Reflected s' (HasState tag s) m s
await_ Proxy# tag
_ = m s -> Reflected s' (HasState tag s) m s
coerce (m s -> Reflected s' (HasState tag s) m s)
-> m s -> Reflected s' (HasState tag s) m s
forall a b. (a -> b) -> a -> b
$ Reified tag (HasSource tag s) m -> m s
forall k (tag :: k) a (m :: * -> *).
Reified tag (HasSource tag a) m -> m a
_await (Reified tag (HasSource tag s) m -> m s)
-> Reified tag (HasSource tag s) m -> m s
forall a b. (a -> b) -> a -> b
$ Reified tag (HasState tag s) m -> Reified tag (HasSource tag s) m
forall k (tag :: k) s (m :: * -> *).
Reified tag (HasState tag s) m -> Reified tag (HasSource tag s) m
_stateSource (Reified tag (HasState tag s) m -> Reified tag (HasSource tag s) m)
-> Reified tag (HasState tag s) m
-> Reified tag (HasSource tag s) m
forall a b. (a -> b) -> a -> b
$ forall (tag :: k) (c :: (* -> *) -> Constraint) (m :: * -> *).
Reifies s' (Reified tag c m) =>
Reified tag c m
forall k1 k2 (s :: k1) (tag :: k2) (c :: (* -> *) -> Constraint)
(m :: * -> *).
Reifies s (Reified tag c m) =>
Reified tag c m
reified @s'
{-# INLINE await_ #-}
instance
( Monad m,
Reifies s' (Reified tag (HasState tag s) m)
) =>
HasSink tag s (Reflected s' (HasState tag s) m)
where
yield_ :: Proxy# tag -> s -> Reflected s' (HasState tag s) m ()
yield_ Proxy# tag
_ = (s -> m ()) -> s -> Reflected s' (HasState tag s) m ()
coerce ((s -> m ()) -> s -> Reflected s' (HasState tag s) m ())
-> (s -> m ()) -> s -> Reflected s' (HasState tag s) m ()
forall a b. (a -> b) -> a -> b
$ Reified tag (HasSink tag s) m -> s -> m ()
forall k (tag :: k) a (m :: * -> *).
Reified tag (HasSink tag a) m -> a -> m ()
_yield (Reified tag (HasSink tag s) m -> s -> m ())
-> Reified tag (HasSink tag s) m -> s -> m ()
forall a b. (a -> b) -> a -> b
$ Reified tag (HasState tag s) m -> Reified tag (HasSink tag s) m
forall k (tag :: k) s (m :: * -> *).
Reified tag (HasState tag s) m -> Reified tag (HasSink tag s) m
_stateSink (Reified tag (HasState tag s) m -> Reified tag (HasSink tag s) m)
-> Reified tag (HasState tag s) m -> Reified tag (HasSink tag s) m
forall a b. (a -> b) -> a -> b
$ forall (tag :: k) (c :: (* -> *) -> Constraint) (m :: * -> *).
Reifies s' (Reified tag c m) =>
Reified tag c m
forall k1 k2 (s :: k1) (tag :: k2) (c :: (* -> *) -> Constraint)
(m :: * -> *).
Reifies s (Reified tag c m) =>
Reified tag c m
reified @s'
{-# INLINE yield_ #-}
instance
( Monad m,
Reifies s' (Reified tag (HasState tag s) m)
) =>
HasState tag s (Reflected s' (HasState tag s) m)
where
state_ :: forall a. Proxy# tag -> (s -> (a, s)) -> Reflected s' (HasState tag s) m a
state_ :: Proxy# tag -> (s -> (a, s)) -> Reflected s' (HasState tag s) m a
state_ Proxy# tag
_ = forall b.
Coercible ((s -> (a, s)) -> m a) b =>
((s -> (a, s)) -> m a) -> b
coerce @((s -> (a, s)) -> m a) (((s -> (a, s)) -> m a)
-> (s -> (a, s)) -> Reflected s' (HasState tag s) m a)
-> ((s -> (a, s)) -> m a)
-> (s -> (a, s))
-> Reflected s' (HasState tag s) m a
forall a b. (a -> b) -> a -> b
$ Reified tag (HasState tag s) m -> forall a. (s -> (a, s)) -> m a
forall k (tag :: k) s (m :: * -> *).
Reified tag (HasState tag s) m -> forall a. (s -> (a, s)) -> m a
_state (forall (tag :: k) (c :: (* -> *) -> Constraint) (m :: * -> *).
Reifies s' (Reified tag c m) =>
Reified tag c m
forall k1 k2 (s :: k1) (tag :: k2) (c :: (* -> *) -> Constraint)
(m :: * -> *).
Reifies s (Reified tag c m) =>
Reified tag c m
reified @s')
{-# INLINE state_ #-}