1

The Reader effect provides a local method which modifies the value to be read within a local scope:

local :: Member (Reader i) r => (i -> i) -> Sem r a -> Sem r a

The function passed to local must not change the type of the data. I would like to be able to avoid this restriction, and have an alternative to local which can modify the type of the reader value.

The obvious way to implement this is with an interpreter-style function like this:

local' :: (i -> j) -> Sem (Reader j ': r) a -> Sem (Reader i ': r) a

The problem with this approach is that it requires that the Reader effect is on the top of the effect stack, which may not be the case.

How can I solve this problem and modify the effect anywhere in the effect stack? If a concrete effect stack can be re-ordered, then this would also solve the problem when used in conjunction with local', but I cannot find any functions to do this either.

runasi
  • 13
  • 2
  • Could you provide an example code which doesn't work? If I understand you right, it's not the problem to implement `local'`, but something related with ordering of effects? – l7r7 Aug 12 '22 at 13:37
  • Yes, I know how to implement `local'` but it is not general enough. If we have a concrete effect stack where `Reader` is not the first in the list, then we cannot use `local'`. For example, somewhere else in the program I might have the effect stack `'[ State (), Reader a ]`. Given a function `a -> b`, I would like to transform this stack into `'[ State (), Reader b ]`. However this is not possible with `local'`, since the effects are in the wrong order. One solution would be to re-order the effects. Another would be to write `local'` in a way such that it works with the effects in any order. – runasi Aug 12 '22 at 14:54
  • Ok I see. Is it possible to use `local' :: Member (Reader a) r => (a -> b) -> InterpreterFor (Reader b) r` as type signature? So instead of using a fixed order of effect you use `Member`, which basically says "this effect must be in the effect stack, but it doesn't matter where" – l7r7 Aug 12 '22 at 15:00
  • That would be more general than the original `local'`, but `InterpreterFor` still requires the effect we are interpreting (in this case `Reader b`) to be on the top of the stack. – runasi Aug 12 '22 at 15:16
  • I'm not sure if that's the case. Do you have an example for that? – l7r7 Aug 12 '22 at 15:21
  • I was looking at the definition `type InterpreterFor e r = forall a . Sem (e : r) a -> Sem r a`, where the effect stack for the parameter requires that `e` is on the top of the stack. However, upon further thought I don't think this actually causes a problem for my use case, and so I think my problem is solved. Thank you for your help! – runasi Aug 12 '22 at 16:30

1 Answers1

0

As mentioned in the comments, using the following type signature doesn't require the effects to be in a fixed order:

local' :: Member (Reader a) r => (a -> b) -> InterpreterFor (Reader b) r

l7r7
  • 1,134
  • 1
  • 7
  • 23