{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeInType #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UnboxedTuples #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-simplifiable-class-constraints -Wno-deprecations #-}
module Capability.Writer
(
HasWriter(..)
, writer
, tell
, listen
, pass
, censor
, HasWriter'
, TypeOf
, WriterLog
, StreamLog
, SinkLog (..)
, module Capability.Accessors
, Reified (..)
) where
import Capability.Accessors
import Capability.Reflection
import Capability.Sink
import Capability.State
import Capability.Stream
import Data.Coerce (Coercible, coerce)
import Data.Kind (Type)
import GHC.Exts (Proxy#, proxy#)
class (Monoid w, Monad m, HasSink tag w m)
=> HasWriter (tag :: k) (w :: Type) (m :: Type -> Type) | tag m -> w
where
writer_ :: Proxy# tag -> (a, w) -> m a
listen_ :: Proxy# tag -> m a -> m (a, w)
pass_ :: Proxy# tag -> m (a, w -> w) -> m a
writer :: forall tag w m a. HasWriter tag w m => (a, w) -> m a
writer :: (a, w) -> m a
writer = Proxy# tag -> (a, w) -> m a
forall k (tag :: k) w (m :: * -> *) a.
HasWriter tag w m =>
Proxy# tag -> (a, w) -> m a
writer_ (Proxy# tag
forall k (a :: k). Proxy# a
proxy# @tag)
{-# INLINE writer #-}
tell :: forall tag w m. HasWriter tag w m => w -> m ()
tell :: w -> m ()
tell = Proxy# tag -> w -> m ()
forall k (tag :: k) a (m :: * -> *).
HasSink tag a m =>
Proxy# tag -> a -> m ()
yield_ (Proxy# tag
forall k (a :: k). Proxy# a
proxy# @tag)
{-# INLINE tell #-}
listen :: forall tag w m a. HasWriter tag w m => m a -> m (a, w)
listen :: m a -> m (a, w)
listen = Proxy# tag -> m a -> m (a, w)
forall k (tag :: k) w (m :: * -> *) a.
HasWriter tag w m =>
Proxy# tag -> m a -> m (a, w)
listen_ (Proxy# tag
forall k (a :: k). Proxy# a
proxy# @tag)
{-# INLINE listen #-}
pass :: forall tag w m a. HasWriter tag w m => m (a, w -> w) -> m a
pass :: m (a, w -> w) -> m a
pass = Proxy# tag -> m (a, w -> w) -> m a
forall k (tag :: k) w (m :: * -> *) a.
HasWriter tag w m =>
Proxy# tag -> m (a, w -> w) -> m a
pass_ (Proxy# tag
forall k (a :: k). Proxy# a
proxy# @tag)
{-# INLINE pass #-}
censor_ :: forall k (tag :: k) w m a. HasWriter tag w m => Proxy# tag -> (w -> w) -> m a -> m a
censor_ :: Proxy# tag -> (w -> w) -> m a -> m a
censor_ Proxy# tag
tag w -> w
f m a
m = Proxy# tag -> m (a, w -> w) -> m a
forall k (tag :: k) w (m :: * -> *) a.
HasWriter tag w m =>
Proxy# tag -> m (a, w -> w) -> m a
pass_ Proxy# tag
tag (m (a, w -> w) -> m a) -> m (a, w -> w) -> m a
forall a b. (a -> b) -> a -> b
$ (,w -> w
f) (a -> (a, w -> w)) -> m a -> m (a, w -> w)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m a
m
censor :: forall tag w m a. HasWriter tag w m => (w -> w) -> m a -> m a
censor :: (w -> w) -> m a -> m a
censor = Proxy# tag -> (w -> w) -> m a -> m a
forall k (tag :: k) w (m :: * -> *) a.
HasWriter tag w m =>
Proxy# tag -> (w -> w) -> m a -> m a
censor_ (Proxy# tag
forall k (a :: k). Proxy# a
proxy# @tag)
{-# INLINE censor #-}
deriving via ((t2 :: (Type -> Type) -> Type -> Type) ((t1 :: (Type -> Type) -> Type -> Type) m))
instance
( forall x. Coercible (m x) (t2 (t1 m) x)
, Monad m, HasWriter tag w (t2 (t1 m)) )
=> HasWriter tag w ((t2 :.: t1) m)
type WriterLog = SinkLog
instance (Monoid w, HasState tag w m)
=> HasWriter tag w (WriterLog m)
where
writer_ :: Proxy# tag -> (a, w) -> WriterLog m a
writer_ Proxy# tag
tag (a
a, w
w) = Proxy# tag -> w -> SinkLog m ()
forall k (tag :: k) a (m :: * -> *).
HasSink tag a m =>
Proxy# tag -> a -> m ()
yield_ Proxy# tag
tag w
w SinkLog m () -> WriterLog m a -> WriterLog m a
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> a -> WriterLog m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
a
{-# INLINE writer_ #-}
listen_ :: forall a. Proxy# tag -> WriterLog m a -> WriterLog m (a, w)
listen_ :: Proxy# tag -> WriterLog m a -> WriterLog m (a, w)
listen_ Proxy# tag
_ WriterLog m a
m = forall b. Coercible (m (a, w)) b => m (a, w) -> b
coerce @(m (a, w)) (m (a, w) -> WriterLog m (a, w)) -> m (a, w) -> WriterLog m (a, w)
forall a b. (a -> b) -> a -> b
$ do
w
w0 <- forall k (tag :: k) s (m :: * -> *). HasState tag s m => m s
forall s (m :: * -> *). HasState tag s m => m s
get @tag
w -> m ()
forall k (tag :: k) s (m :: * -> *). HasState tag s m => s -> m ()
put @tag w
forall a. Monoid a => a
mempty
a
a <- WriterLog m a -> m a
coerce WriterLog m a
m
w
w <- 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 (w -> m ()) -> w -> m ()
forall a b. (a -> b) -> a -> b
$! w
w0 w -> w -> w
forall a. Semigroup a => a -> a -> a
<> w
w
(a, w) -> m (a, w)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
a, w
w)
{-# INLINE listen_ #-}
pass_ :: forall a. Proxy# tag -> WriterLog m (a, w -> w) -> WriterLog m a
pass_ :: Proxy# tag -> WriterLog m (a, w -> w) -> WriterLog m a
pass_ Proxy# tag
_ WriterLog m (a, w -> w)
m = forall b. Coercible (m a) b => m a -> b
coerce @(m a) (m a -> WriterLog m a) -> m a -> WriterLog m a
forall a b. (a -> b) -> a -> b
$ do
w
w0 <- forall k (tag :: k) s (m :: * -> *). HasState tag s m => m s
forall s (m :: * -> *). HasState tag s m => m s
get @tag
w -> m ()
forall k (tag :: k) s (m :: * -> *). HasState tag s m => s -> m ()
put @tag w
forall a. Monoid a => a
mempty
(a
a, w -> w
f) <- WriterLog m (a, w -> w) -> m (a, w -> w)
coerce @_ @(m (a, w -> w)) WriterLog m (a, w -> w)
m
w
w <- 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 (w -> m ()) -> w -> m ()
forall a b. (a -> b) -> a -> b
$! w
w0 w -> w -> w
forall a. Semigroup a => a -> a -> a
<> w -> w
f w
w
a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
a
{-# INLINE pass_ #-}
type HasWriter' (tag :: k) = HasWriter tag (TypeOf k tag)
data instance Reified tag (HasWriter tag w) m = ReifiedWriter
{ Reified tag (HasWriter tag w) m -> Reified tag (HasSink tag w) m
_writerSink :: Reified tag (HasSink tag w) m,
Reified tag (HasWriter tag w) m -> forall a. (a, w) -> m a
_writer :: forall a. (a, w) -> m a,
Reified tag (HasWriter tag w) m -> forall a. m a -> m (a, w)
_listen :: forall a. m a -> m (a, w),
Reified tag (HasWriter tag w) m -> forall a. m (a, w -> w) -> m a
_pass :: forall a. m (a, w -> w) -> m a
}
instance
( Monoid w,
Monad m,
Reifies s (Reified tag (HasWriter tag w) m)
) =>
HasSink tag w (Reflected s (HasWriter tag w) m)
where
yield_ :: Proxy# tag -> w -> Reflected s (HasWriter tag w) m ()
yield_ Proxy# tag
_ = (w -> m ()) -> w -> Reflected s (HasWriter tag w) m ()
coerce ((w -> m ()) -> w -> Reflected s (HasWriter tag w) m ())
-> (w -> m ()) -> w -> Reflected s (HasWriter tag w) m ()
forall a b. (a -> b) -> a -> b
$ Reified tag (HasSink tag w) m -> w -> m ()
forall k (tag :: k) a (m :: * -> *).
Reified tag (HasSink tag a) m -> a -> m ()
_yield (Reified tag (HasSink tag w) m -> w -> m ())
-> Reified tag (HasSink tag w) m -> w -> m ()
forall a b. (a -> b) -> a -> b
$ Reified tag (HasWriter tag w) m -> Reified tag (HasSink tag w) m
forall k (tag :: k) w (m :: * -> *).
Reified tag (HasWriter tag w) m -> Reified tag (HasSink tag w) m
_writerSink (Reified tag (HasWriter tag w) m -> Reified tag (HasSink tag w) m)
-> Reified tag (HasWriter tag w) m -> Reified tag (HasSink tag w) m
forall a b. (a -> b) -> a -> b
$ forall (tag :: k) (c :: Capability) (m :: * -> *).
Reifies s (Reified tag c m) =>
Reified tag c m
forall k1 k2 (s :: k1) (tag :: k2) (c :: Capability) (m :: * -> *).
Reifies s (Reified tag c m) =>
Reified tag c m
reified @s
{-# INLINE yield_ #-}
instance
( Monad m,
Monoid w,
Reifies s (Reified tag (HasWriter tag w) m)
) =>
HasWriter tag w (Reflected s (HasWriter tag w) m)
where
writer_ :: forall a. Proxy# tag -> (a, w) -> Reflected s (HasWriter tag w) m a
writer_ :: Proxy# tag -> (a, w) -> Reflected s (HasWriter tag w) m a
writer_ Proxy# tag
_ = forall b. Coercible ((a, w) -> m a) b => ((a, w) -> m a) -> b
coerce @((a, w) -> m a) (((a, w) -> m a) -> (a, w) -> Reflected s (HasWriter tag w) m a)
-> ((a, w) -> m a) -> (a, w) -> Reflected s (HasWriter tag w) m a
forall a b. (a -> b) -> a -> b
$ Reified tag (HasWriter tag w) m -> forall a. (a, w) -> m a
forall k (tag :: k) w (m :: * -> *).
Reified tag (HasWriter tag w) m -> forall a. (a, w) -> m a
_writer (forall (tag :: k) (c :: Capability) (m :: * -> *).
Reifies s (Reified tag c m) =>
Reified tag c m
forall k1 k2 (s :: k1) (tag :: k2) (c :: Capability) (m :: * -> *).
Reifies s (Reified tag c m) =>
Reified tag c m
reified @s)
{-# INLINE writer_ #-}
listen_ :: forall a. Proxy# tag -> Reflected s (HasWriter tag w) m a -> Reflected s (HasWriter tag w) m (a, w)
listen_ :: Proxy# tag
-> Reflected s (HasWriter tag w) m a
-> Reflected s (HasWriter tag w) m (a, w)
listen_ Proxy# tag
_ = forall b. Coercible (m a -> m (a, w)) b => (m a -> m (a, w)) -> b
coerce @(m a -> m (a, w)) ((m a -> m (a, w))
-> Reflected s (HasWriter tag w) m a
-> Reflected s (HasWriter tag w) m (a, w))
-> (m a -> m (a, w))
-> Reflected s (HasWriter tag w) m a
-> Reflected s (HasWriter tag w) m (a, w)
forall a b. (a -> b) -> a -> b
$ Reified tag (HasWriter tag w) m -> forall a. m a -> m (a, w)
forall k (tag :: k) w (m :: * -> *).
Reified tag (HasWriter tag w) m -> forall a. m a -> m (a, w)
_listen (forall (tag :: k) (c :: Capability) (m :: * -> *).
Reifies s (Reified tag c m) =>
Reified tag c m
forall k1 k2 (s :: k1) (tag :: k2) (c :: Capability) (m :: * -> *).
Reifies s (Reified tag c m) =>
Reified tag c m
reified @s)
{-# INLINE listen_ #-}
pass_ :: forall a. Proxy# tag -> Reflected s (HasWriter tag w) m (a, w -> w) -> Reflected s (HasWriter tag w) m a
pass_ :: Proxy# tag
-> Reflected s (HasWriter tag w) m (a, w -> w)
-> Reflected s (HasWriter tag w) m a
pass_ Proxy# tag
_ = forall b.
Coercible (m (a, w -> w) -> m a) b =>
(m (a, w -> w) -> m a) -> b
coerce @(m (a, w -> w) -> m a) ((m (a, w -> w) -> m a)
-> Reflected s (HasWriter tag w) m (a, w -> w)
-> Reflected s (HasWriter tag w) m a)
-> (m (a, w -> w) -> m a)
-> Reflected s (HasWriter tag w) m (a, w -> w)
-> Reflected s (HasWriter tag w) m a
forall a b. (a -> b) -> a -> b
$ Reified tag (HasWriter tag w) m -> forall a. m (a, w -> w) -> m a
forall k (tag :: k) w (m :: * -> *).
Reified tag (HasWriter tag w) m -> forall a. m (a, w -> w) -> m a
_pass (forall (tag :: k) (c :: Capability) (m :: * -> *).
Reifies s (Reified tag c m) =>
Reified tag c m
forall k1 k2 (s :: k1) (tag :: k2) (c :: Capability) (m :: * -> *).
Reifies s (Reified tag c m) =>
Reified tag c m
reified @s)
{-# INLINE pass_ #-}