-
Notifications
You must be signed in to change notification settings - Fork 17
Open
Description
I've been thinking that it could be nice to have combinators that can turn this fin of doom.
f = runEff \io -> do
evalState 1 \s -> do
withFile io "file.txt" ReadMode \f -> do
withConnection io url \c -> do
undefinedInto this beauty.
f = runEff \io -> do
withEff3 (evalState 1) (withFile io "file.txt" ReadMode) (withConnection io url) \s f c -> do
undefined
-- or
f = runEff \io -> do
withEff3
(evalState 1)
(withFile io "file.txt" ReadMode)
(withConnection io url)
\s f c -> do
undefinedCan it be done? Well, apparently not by me! My haskell-fu is too weak, and so is my intuition about those type tags.
Naive approach.
withEff2
:: forall f1 e1 f2 e2 es r
. ((f1 e1 -> Eff (e1 :& es) r) -> Eff es r)
-> ((f2 e2 -> Eff (e2 :& e1 :& es) r) -> Eff es r) -- This is cheating with `e1 :&`, but whatever, we have other problems for now.
-> ( f1 e1
-> f2 e2
-> Eff (e2 :& e1 :& es) r
)
-> Eff es r
withEff2 f1 f2 f = f1 \a1 -> do
useImpl $ f2 \a2 -> do f a1 a2Problem is, I can't call this function with any handler, due to missing forall.
Couldn't match type: forall (e :: Effects).
State Int e -> Eff (e :& es) a
with: f10 e10 -> Eff (e10 :& es) a
Expected: (f10 e10 -> Eff (e10 :& es) a) -> Eff es a
Actual: (forall (e :: Effects). State Int e -> Eff (e :& es) a) -> Eff es a
With forall.
withEff2
:: ((forall e1. f1 e1 -> Eff (e1 :& es) r) -> Eff es r)
-> ((forall e2. f2 e2 -> Eff (e2 :& e1 :& es) r) -> Eff es r) -- Cheating.
-> ( forall e3 e4
. f1 e3
-> f2 e4
-> Eff (e4 :& e3 :& es) r
)
-> Eff es r
withEff2 f1 f2 f = f1 \a1 -> do
useImpl $ f2 \a2 -> do f (unsafeCoerce a1) a2But now I can't convince GHC that those es are the same.
And there is this :& e1 problem, that doesn't let me call this function either.
So I guess I want this:
withEff2
:: ((forall e1. f1 e1 -> Eff (e1 :& es) r) -> Eff es r)
-> ((forall e2. f2 e2 -> Eff (e2 :& es) r) -> Eff es r)
-> ( forall e3 e4
. f1 e3
-> f2 e4
-> Eff (e4 :& e3 :& es) r
)
-> Eff es r
withEff2 f1 f2 f = f1 \a1 -> do
useImpl $ f2 \a2 -> do unsafeCoerce f a1 a2Which I can call, and works like a charm.
g = runEff \io -> do
withEff2 (evalState (0 :: Int)) (withFile io "file.txt" ReadMode) \a b -> do
put a 2
hIsEOF bThe last problem is that this doesn't work with less polymorphic handlers like try or runState, but I can live with that.
Metadata
Metadata
Assignees
Labels
No labels