1

Regarding Control.Applicative, If I have the following expression:

f = (expr1 <|> expr2) <* expr3

Are the brackets necessary? That is, will expr3 get evaluated (and thrown away) regardless of which branch is taken?

Mike Menzel
  • 583
  • 2
  • 12

2 Answers2

10

You can ask ghci for precedence information:

Prelude Control.Applicative> :i <|>
class Applicative f => Alternative f where
  ...
  (<|>) :: f a -> f a -> f a
  ...
    -- Defined in `Control.Applicative'
infixl 3 <|>
Prelude Control.Applicative> :i <*
class Functor f => Applicative f where
  ...
  (<*) :: f a -> f b -> f a
    -- Defined in `Control.Applicative'
infixl 4 <*

The relevant bits there are these two lines:

infixl 3 <|>
infixl 4 <*

Since <* has a higher precedence (4), it binds tighter; so yes, the brackets are needed to prevent that from being parsed as expr1 <|> (expr2 <* expr3).

Daniel Wagner
  • 145,880
  • 9
  • 220
  • 380
3

<|> has a precedence of 3; <* of 4. So the parentheses are required.

$ ghci
λ import Control.Applicative
λ :info <|>
class Applicative f => Alternative f where
  ...
  (<|>) :: f a -> f a -> f a
  ...
    -- Defined in `Control.Applicative'
infixl 3 <|>
λ :info <*
class Functor f => Applicative f where
  ...
  (<*) :: f a -> f b -> f a
    -- Defined in `Control.Applicative'
infixl 4 <*
Jon Purdy
  • 53,300
  • 8
  • 96
  • 166