polysemy-scoped-fs-0.1.0.0: src/Polysemy/ScopedReader.hs
{-|
Copyright : (c) Hisaket VioletRed, 2022
License : AGPL-3.0-or-later
Maintainer : hisaket@outlook.jp
Stability : experimental
This module provides a scoped-reader manner.
In contrast to a normal 'Reader' effect, this manner makes connection of parameter type and effect explicit.
Example\:
>>> import Polysemy ( interpret, runM, embed )
>>> import Polysemy.Output ( Output (Output), output, runOutputSem )
>>> :{
runDebug :: Member (Output String) r => String -> InterpreterFor (ScopedReader String (Output String)) r
runDebug = runScopedReader \i -> interpret \(Output o) -> output $ "[" <> i <> "] " <> o
:}
>>> :{
runM $ runOutputSem (embed . putStrLn) $ runDebug "root" do
scopedReader $ output "test message 0"
scopedLocal (<> ".scope-A") do
scopedReader $ output "test message 1"
scopedReader $ output "test message 2"
scopedLocal (<> ".scope-B") do
scopedReader $ output "test message 3"
:}
[root] test message 0
[root.scope-A] test message 1
[root.scope-A] test message 2
[root.scope-A.scope-B] test message 3
-}
{-# LANGUAGE PartialTypeSignatures #-}
{-# OPTIONS_GHC -Wno-partial-type-signatures #-}
module Polysemy.ScopedReader where
import Polysemy
( Member, Sem, raise, raiseUnder, InterpreterFor, transform )
import Polysemy.Scoped.Path ( ScopedP, scopedP_local, runScopedP )
import Polysemy.Scoped.Path.Internal ( interpretH' )
import Control.Category ((>>>))
import Polysemy.Internal ( liftSem )
import Polysemy.Internal.Union
( ElemOf (Here), Union (Union), Weaving (Weaving) )
scopedLocal
:: ∀i p resource effect r
. Member (ScopedReader i effect) r
=> (i -> i) -> InterpreterFor (ScopedFix i effect) r
scopedLocal f = scopedFix . scopedP_local f () . raiseUnder
scopedReader :: Member (ScopedReader i effect) r => Sem (effect ': r) a -> Sem r a
scopedReader = scopedEffect
type ScopedReader i effect = ScopedFix i effect
runScopedReader :: (i -> InterpreterFor effect r) -> i -> Sem (ScopedReader i effect ': r) a -> Sem r a
runScopedReader int localEnv =
interpretH' \(Weaving e s wv ex ins) ->
let send' :: _ -> Sem (_ ': _) _
send' e' =
liftSem $ Union Here
$ Weaving e' s (raise . runScopedReader int localEnv . wv) ex ins
in case e of
ScopedEffect e' -> int localEnv $ send' e'
ScopedFix e' ->
runScopedP (\() inner -> inner localEnv) (runScopedReader int) $ send' e'
data ScopedFixP p resource effect m a where
ScopedEffect :: effect m a -> ScopedFixP p resource effect m a
ScopedFix
:: ScopedP p resource (ScopedFixP p resource effect) m a
-> ScopedFixP p resource effect m a
type ScopedFix = ScopedFixP ()
scopedEffect :: Member (ScopedFixP p resource effect) r => Sem (effect ': r) a -> Sem r a
scopedEffect = transform ScopedEffect
scopedFix
:: Member (ScopedFixP p resource effect) r
=> Sem (ScopedP p resource (ScopedFixP p resource effect) ': r) a
-> Sem r a
scopedFix = transform ScopedFix