{-# LANGUAGE TemplateHaskell #-}
module Polysemy.View
(
View (..)
, see
, viewToState
, viewToInput
) where
import Polysemy
import Polysemy.Input
import Polysemy.State
import Polysemy.Tagged
data View v m a where
See :: View v m v
makeSem ''View
viewToInput
:: forall v i r a
. Member (Input i) r
=> (i -> v)
-> Sem (View v ': r) a
-> Sem r a
viewToInput f = interpret $ \case
See -> f <$> input
viewToState
:: forall v s r a
. Member (State s) r
=> (s -> Sem r v)
-> Sem (View v ': r) a
-> Sem r a
viewToState f = do
evalState Dirty
. untag @"view" @(State (Cached v))
. intercept @(State s)
( \case
Get -> get
Put s -> do
put s
tag @"view" @(State (Cached v)) $ put $ Dirty @v
)
. reinterpret @(View v)
( \case
See -> do
dirty <- tagged @"view" $ get @(Cached v)
case dirty of
Dirty -> do
s <- get
v' <- raise $ f s
tagged @"view" $ put $ Cached v'
pure v'
Cached v -> pure v
)
data Cached a = Cached a | Dirty
deriving (Eq, Ord, Show, Functor)