# 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? I guess we should try to get

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

at some point @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?

🚧 a work in progress effect system for Haskell 🚧. Contribute to hasura/eff development by creating an account on GitHub. Even if we added `lift` later, we probably want these as more "inferable" variants, because they should produce much more sane type errors 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 ``````-- 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'
`````` 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