Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Passing arguments to control operators is often backwards #4

Open
lexi-lambda opened this issue Dec 2, 2019 · 0 comments
Open

Passing arguments to control operators is often backwards #4

lexi-lambda opened this issue Dec 2, 2019 · 0 comments

Comments

@lexi-lambda
Copy link

Control operators have two kinds of arguments: function arguments (which are arrows) and arrow arguments. For an example, consider a function like local:

local :: ArrowReader r arr => arr e a -> arr (e, r) a

Like local from MonadReader, this runs the argument in a modified environment (though unlike the MonadReader version, it accepts the environment directly instead of being given a function to apply to it). Using it in arrow notation looks like this:

y <- (| local (f -< x) |) r

This works okay when the argument to local is small, but it becomes very confusing when the argument command is large. For example, I might want to run a whole block with a modified environment, so I would have to write something like this:

r <- ask -< ()
w <- (| local (do
          y <- f -< x
          z <- g -< y
          h -< (y, z))
     |) (foo $ bar r)

I think this looks totally backwards. Very often, when writing monadic code, I do something like this:

w <- flip local (foo . bar) $ do
       y <- f x
       z <- g y
       h y z

But there isn’t any way to write code that way in arrow notation. This means that if I have a series of nested control operators, I end up with something like

(| withRecordInconsistency
   ((| withRecordDependencies
       ((| mapErrorA (f -< (e, s))
         |) \e -> "in permission for role " <> roleName <<> ": " <> e)
     |) metadataObject schemaObject)
 |) metadataObject

which looks terrible and is hard to read. The equivalent monadic code it was adapted from looks like

withRecordInconsistency metadataObject $
  withRecordDependencies metadataObject schemaObject $
    modifyErr (\e -> "in permission for role " <> rn <<> ": " <> e) $
      m

which is far better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant