# raiseUnder and multiple effect interpretation - Polysemy

Welcome to the Functional Programming Zulip Chat Archive. You can join the chat here.

What's the right way to do this:

``````interp1 :: Member e3 r => Sem (e1 : e2 : r) a -> Sem r a

interp2 :: Sem (e1 : e2 : r) a -> Sem r a
interp2 = interp_e3 . interp1 . raiseUnder???
``````

It seems that I would need to introduce an effect two levels deep, but I don't see a combinator for that. Is there a better way?

to be clear, I want `e3` not to be needed in the outside interpreter stack

which works fine when `interp1` is a single effect, with `raiseUnderN`

I guess we should try to get

``````lift :: forall effs1 effs2 a. Lift effs1 effs2 => Sem effs1 a -> Sem effs2 a
``````

at some point

(from `eff`)

@TheMatten pls2check!

These combinators are like raiseUnder, but place the new effect at the second and third position in the list. This is for interpreters that consume two effects, delegating to two other interpreters...

@Torsten Schmits Cool, thanks!
While talking about "shuffling" effects around, what about porting `lift` from `eff`, which would allow us to reorder and add effects freely?

would love to! you wanna merge this anyway for the time being?

ah, I see you already approved. :rocket:

Even if we added `lift` later, we probably want these as more "inferable" variants, because they should produce much more sane type errors

We would just turn them into call to `lift` in that case

Well this is rather unfortunate! `raise2Under` actually means "raise an effect under two effects", and the existing `raiseUnder2` actually means "raise two effects under the current one" :sweat_smile:

again with the self-recursive calls where it's entirely non-obvious to me how this is terminating at all -_- (wrt `raiseUnder`)

That recursive use should mostly matter in higher-order effects, where you call it on your argument to actually conform to "latest" row

So it stops at some point, because you don't have infinitely nested higher-order calls :slight_smile:

``````-- inspired by
-- https://github.com/hasura/eff/blob/bf0520d0fb0644fef2bb78d0cfa289efdc9fc851/eff/src/Control/Effect/Internal.hs#L688

class Raise (r :: [Effect]) (r' :: [Effect]) where
raiseUnion :: Union r m a -> Union r' m a

instance {-# overlapping #-} Raise r r where
raiseUnion = id

instance (r' ~ (_0:r''), Raise r r'') => Raise r r' where
raiseUnion = (\(Union n w) -> Union (There n) w) . raiseUnion

class Subsume (r :: [Effect]) (r' :: [Effect]) where
subsumeUnion :: Union r m a -> Union r' m a

instance {-# incoherent #-} Raise r r' => Subsume r r' where
subsumeUnion = raiseUnion

instance (Member e r', Subsume r r') => Subsume (e:r) r' where
subsumeUnion = either subsumeUnion injWeaving . decomp

instance Subsume '[] r where
subsumeUnion = absurdU

raise' :: Subsume r r' => Sem r a -> Sem r' a
raise' = hoistSem \$ hoist raise' . subsumeUnion

raise :: Sem r a -> Sem (e ': r) a
raise = raise'

raiseUnder :: Sem (e1 ': r) a -> Sem (e1 ': (e2 ': r)) a
raiseUnder = raise'

raiseUnder2 :: Sem (e1 ': r) a -> Sem (e1 ': (e2 ': (e3 ': r))) a
raiseUnder2 = raise'

raiseUnder3 :: Sem (e1 ': r) a -> Sem (e1 ': (e2 ': (e3 ': (e4 ': r)))) a
raiseUnder3 = raise'

subsume :: Member e r => Sem (e ': r) a -> Sem r a
subsume = raise'
``````

A little bit of incoherence and it can work with both concrete stacks and "polymorphic tails"

Should I open a PR? Or do you have some ideas for names? (those operators in `eff` are nice)

Maybe something like

``````-------------------------------------------------------------------------------
-- | Raises effect stack by arbitrary number of effects.
raise' :: Raise r r' => Sem r a -> Sem r' a
raise' = hoistSem \$ hoist raise' . raiseUnion

raise :: Sem r a -> Sem (e ': r) a
raise = raise'

raiseUnder :: Sem (e1 ': r) a -> Sem (e1 ': (e2 ': r)) a
raiseUnder = subsume'

raiseUnder2 :: Sem (e1 ': r) a -> Sem (e1 ': (e2 ': (e3 ': r))) a
raiseUnder2 = subsume'

raiseUnder3 :: Sem (e1 ': r) a -> Sem (e1 ': (e2 ': (e3 ': (e4 ': r)))) a
raiseUnder3 = subsume'

class Raise (r :: [Effect]) (r' :: [Effect]) where
raiseUnion :: Union r m a -> Union r' m a

instance {-# overlapping #-} Raise r r where
raiseUnion = id

instance (r' ~ (_0:r''), Raise r r'') => Raise r r' where
raiseUnion = (\(Union n w) -> Union (There n) w) . raiseUnion

-------------------------------------------------------------------------------
-- | Allows reordering and adding known effects on top of effect stack, as long
-- as polymorphic tail of new stack is 'raise'-d version of the original one.
subsume' :: Subsume r r' => Sem r a -> Sem r' a
subsume' = hoistSem \$ hoist subsume' . subsumeUnion

subsume :: Member e r => Sem (e ': r) a -> Sem r a
subsume = subsume'

class Subsume (r :: [Effect]) (r' :: [Effect]) where
subsumeUnion :: Union r m a -> Union r' m a

instance {-# incoherent #-} Raise r r' => Subsume r r' where
subsumeUnion = raiseUnion

instance (Member e r', Subsume r r') => Subsume (e:r) r' where
subsumeUnion = either subsumeUnion injWeaving . decomp

instance Subsume '[] r where
subsumeUnion = absurdU
``````

where names could be switched to `raise` and `raiseN` (for `N` in `[1..3]`) in v2

TheMatten said:

(Haha, I wonder how many people used https://hackage.haskell.org/package/polysemy-zoo-0.7.0.0/docs/Polysemy-Operators.html :big_smile: )

ooh, never seen those. not sure I find them very readable though, but I'd have to use them a bit to get an impression

I say make a PR and wait for comments over there