Polysemy: EffectRow
As seen in the previous log we ended up with:
displayFile path = do
trace $ "Displaying " <> path
content <- embed $ readFile path
embed $ putStr content
return $ length content
intrDisplayFile =
runM
. traceToStdout
As you can see '[Trace, Embed IO]
is repeated twice:
- During expression definition
- During interpretation
It's actually an EffectRow
which represents a type-level list of Effect
.
This duplication looks nice but would be impractical.
For example, switching order in the expression:
Would create an error:
src/Intro.hs:24:36-63: error:
• Couldn't match type: Embed IO
with: Trace
Expected: Sem '[Trace, Embed IO] Int
Actual: Sem '[Embed IO, Trace] Int
• In the first argument of ‘intrDisplayFile’, namely
‘(displayFile "/tmp/hello.txt")’
In the first argument of ‘(>>=)’, namely
‘intrDisplayFile (displayFile "/tmp/hello.txt")’
In the expression:
intrDisplayFile (displayFile "/tmp/hello.txt") >>= print
|
24 | mainDisplayFile = intrDisplayFile (displayFile "/tmp/hello.txt") >>= print
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
We would have the same issue calling it from another function:
displayFile' = displayFile
src/Intro.hs:24:16-26: error:
• Couldn't match type: Trace
with: Embed IO
Expected: FilePath -> Sem '[Embed IO, Trace] Int
Actual: FilePath -> Sem '[Trace, Embed IO] Int
• In the expression: displayFile
In an equation for ‘displayFile'’: displayFile' = displayFile
|
24 | displayFile' = displayFile
|
Actually '[Trace, Embed IO]
is a concrete EffectRow
.
There is also a constrained
EffectRow
, which is defined like this:
displayFile path = do
trace $ "Displaying " <> path
content <- embed $ readFile path
embed $ putStr content
return $ length content
we can also define them one by one:
displayFile' = displayFile
in these example, function definitonsare unchanged.
However the EffectRow
is now polymorphic and has constraints attached to it.
Now we are able to call any function with other EffectRow
(as long as it fits the constraints).
While concrete EffectRow
is mandatory at interpretation time, during expression building it's limiting.
See the full the code here.