Closed goertzenator closed 2 years ago
You get order independence in the latter two examples because you're using the :>
constraint (via the :>>
type family).
I think this change should solve your problem:
-runApp :: Eff '[Trace, IOE] a -> IO a
+runApp :: '[Trace, IOE] :>> es => Eff es a -> IO a
runApp = runIOE . runTraceStdout
Also, the correct order in the first example is defined by the order of your run*
functions. You need to handle the Trace
effect before you can handle the IOE
effect, so Trace
gets popped off the head of the type-level list first.
In general you should always try to use :>
or :>>
to avoid requiring a concrete ordering.
I think this change should solve your problem:
-runApp :: Eff '[Trace, IOE] a -> IO a +runApp :: '[Trace, IOE] :>> es => Eff es a -> IO a runApp = runIOE . runTraceStdout
That fails with "Couldn't match type βesβ with β'[Trace, IOE]β". To fully discharge an Eff
it needs to be brought down to a concrete Eff '[]
or Eff '[IOE]
before you runPure
/runIOE
.
Oh yeah you're right π€¦ββοΈ Sorry about that.
For the case where you're handling effects, you do need to know there are no effects remaining. And :>
/:>>
doesn't do that for you.
Yeah, unfortunately we can't have that. I think the reason is basically that Haskell doesn't have type-level Set
s (except for typeclasses; but it would suck trying to implement many advanced effects features with typeclasses, unless someday we get proper anonymous implicit arguments like Dotty).
I wrestled with the my top-level
run
function for a while which boiled down to this:My actual app of course has a bigger list of effects. It was surprising to see order dependence here when most of Cleff usage has order independence, for example:
Not a huge deal; I can easily work around this now that I know about it. But, is there a way to specify the effects for
runApp
in an order independent manner?