ekmett / machines

Networks of composable stream transducers
Other
340 stars 46 forks source link

local in PlanT's MonadReader instance only works up to first yield/awaits #94

Open ivan-timokhin opened 7 years ago

ivan-timokhin commented 7 years ago

This function:

testLocal :: [Int]
testLocal =
  execWriter . flip runReaderT 1 . runT_ . construct . local (+ 1) $ do
    r <- ask
    tell [r]
    yield r
    r' <- ask
    tell [r']

evaluates to [2,1]; i.e. local only applies to the first ask.

The problem is that in the definition of local:

  local f m = PlanT $ \kp ke kr kf -> local f (runPlanT m kp ke kr kf)

base monad's local is only applied to the outermost monadic layer produced. That is, since r in PlanT is specialized to Step k o (MachineT m k o) in construct, the ‘result’ of the computation can actually contain other layers of the base monad within it, which are unaffected by local. Thus, second ask in the example above produces the original environment, since it is ‘hidden’ within the Yield constructor.