Polysemy: Interpretation and effects inline injection
In a previous log we have seen a way to cache computation and a way to inject effects.
Let see what it take to build a caching effect:
data Cache k v (m :: Type -> Type) a where
Cached :: k -> Cache k v m v
As opposed to View
, we have a cache per key and not a global cache, it could lead to memory leaks.
We can use it as follows:
app = do
name0 <- cached "name"
embed $ putStrLn $ "Your name is " <> name0
location0 <- cached "location"
embed $ putStrLn $ "Your location is " <> location0
name1 <- cached "name"
location1 <- cached "location"
embed $ putStrLn $ "Hello " <> name1 <> " from " <> location1
It let use with the interpreter:
runCache f =
evalState mempty
. interpret (\case
Cached k -> do
currentCache <- get @(M.Map k v)
case currentCache M.!? k of
Nothing -> do
v <- raise $ f k
put $ M.insert k v currentCache
return v
Just v -> return v
)
. raiseUnder @(State (M.Map k v))
It can be understood this way:
- Add a new effect with
raiseUnder
(so we have(State (M.Map k v) ': r)
) - Get current cache
- Run the computation when key is missing (here we are forced to use
raise
sincef
only givesSem r
) - Run the
State
effect
Finally, here's what it gives:
What's your name?
Gautier
Your name is Gautier
What's your location?
France
Your location is France
Hello Gautier from France
See the full the code here.