This currently does what I intend:

import Control.Arrow (Kleisli, runKleisli)
import Control.Applicative (WrappedArrow(WrapArrow))
import Control.Lens.Traversal (preview)

nested :: Request -> Maybe Response
nested = runKleisli . unwrapArrow
       $ WrapArrow (Kleisli (preview (prefixed "/name") >=> app1))
     <|> WrapArrow (Kleisli (preview (prefixed "/surname") >=> app2))

    prefixed :: Text -> Prism' Request Request
    prefixed = _

    app1,app2 :: Request -> Maybe Response
    app1 = _
    app2 = _

The idea here is to implement a kind of nested HTTP routing. Given the already existing applications app1 and app2, I want to reroute the incoming Request to either of those applications based on whether the path of the Request is prefixed with "/name" or "/surname". The prefixed Prism' strips such prefix from the Request path if present, otherwise it fails.

However I'd like to get rid, somehow, of WrapArrow, Kleisli and preview, and possibly, runKleisli . unwrapArrow. I suspect that this can be done with Control.Lens.Wrapped or Data.Profuntor but I still can't see exactly how.

I wouldn't like to a add an extra dependency for this case but I'm currently using lens in my project, so anything from lens or its dependencies is welcome.

  • \$\begingroup\$ @RubberDuck, hope it's more understandable now. \$\endgroup\$ – Danny Navarro Apr 17 '15 at 11:59
  • \$\begingroup\$ Welcome to Code Review @DannyNavarro! \$\endgroup\$ – RubberDuck Apr 17 '15 at 12:03

I came out with this:

nested :: Request -> Maybe Response
nested = nest [ (prefixed "/name", app1)
              , (prefixed "/surname", app2)

    nest xs request =
        getAlt $ foldMap (Alt . (\(p,a) -> reroute p a request)) xs

    reroute p app = preview p >=> app

Alt is only available in base-, however it shouldn't be difficult to implement your own Alt.

  • \$\begingroup\$ I'm a leaving it open for a few days more in case someone comes with something better. \$\endgroup\$ – Danny Navarro Apr 17 '15 at 14:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.