13

I've had the luxury of learning a bit of Idris lately and one thing I've found extremely convenient is the !-notation, which let's me shorten monadic code inside a do block such as

a' <- a
b' <- b
c' <- c
someFunction a' b' c'

to the much nicer

someFunction !a !b !c

Now when I write code in Haskell, I'm looking for something similar but as far as I can tell it doesn't exist (and the bang character is obviously already used for strict pattern matching). Is there any way to avoid having a bunch of trivial left arrows inside a do block? Perhaps an extension that adds a rewriting rule, or something to that effect?

Sridhar Ratnakumar
  • 81,433
  • 63
  • 146
  • 187
Karl
  • 1,143
  • 6
  • 20

3 Answers3

21

Since every monad is an Applicative (with GHC >= 7.10) we can write

someFunction <$> a <*> b <*> c

Note that if someFunction returns a monadic value of type m T, the above will return m (m T), which is likely not what we want (as @pigworker points out below). We can however join the two layers together:

join $ someFunction <$> a <*> b <*> c
chi
  • 111,837
  • 3
  • 133
  • 218
6

An alternative to @chi's answer is liftA3 someFunction a b c (with join if needed).

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
2

Speaking of arrows...

import Control.Arrow

a' = Kleisli $ const a
b' = Kleisli $ const b
c' = Kleisli $ const c

foo = (`runKleisli`()) $
  (a' &&& b') &&& c' >>> uncurry (uncurry someFunction)

Not that I recommend this.

leftaroundabout
  • 117,950
  • 5
  • 174
  • 319