Fresheyeball
Fresheyeball

Reputation: 30015

What is <|> in haskell?

I am still learning haskell and looking at the snap web framework. In their hello world example there is a thingy that looks like <|>

site :: Snap ()
site =
    ifTop (writeBS "hello world") <|>
    route [ ("foo", writeBS "bar")
          , ("echo/:echoparam", echoHandler)
          ] <|>
    dir "static" (serveDirectory ".")

Googling for this is surprisingly challenging, and the snap documentation simply uses <|> as a noun. What is it, and what does it do?

Upvotes: 10

Views: 378

Answers (3)

David Schalk
David Schalk

Reputation: 110

I agree with Xeo to the extent that <|> has the effect of ignoring the empty list in [] <|> [1,2,3], but under the hood the compiler might be concatenating the empty list with the non-empty list. I have ghci set up to automatically display the types of what it prints. Here are some results which suggest that, in the case of lists, <|> and ++ might be equivalent:

λ: [] <|> [3,4]
[3,4]
it :: Num a => [a]
λ: [] ++ [3,4]
[3,4]
it :: Num a => [a]
λ: [1,2] <|> [3,4]
[1,2,3,4]
it :: Num a => [a]
λ: [1,2] ++ [3,4]
[1,2,3,4]
it :: Num a => [a]
λ: :t (<|>) [1,2] [3,4]
(<|>) [1,2] [3,4] :: Num a => [a]
λ: :t (++) [1,2] [3,4]
(++) [1,2] [3,4] :: Num a => [a]
λ: [1,2] <|> [] <|> [3,4]
[1,2,3,4]

Well, <|> has the effect of ++ in the above examples, but there is more than that going on. At https://hackage.haskell.org/package/parsec-3.0.0/docs/Text-ParserCombinators-Parsec-Prim.html we read this about <|>: "This combinator is defined equal to the mplus member of the MonadPlus class and the (Control.Applicative.<|>) member of Control.Applicative.Alternative." Turning to the Hackage "Control.Monad" discussion we read: "msum :: MonadPlus m => [m a] -> m a Source" followed by "This generalizes the list-based concat function." The answer to the question, "What does <|> do?", is rooted in understanding what Haskell compilers do when they encounter <|>, say in "[] <|> [1,2,3]"? Do they just ignore []? Do they execute the concatenation routine? There are steps involved in just figuring out what do do with this strangely overloaded operator. It's no wonder that programmers are mystified by it, and settle for knowing little more than the effect of employing it in special use cases.

<|> is useful for jumping out of recursive loops as soon as a condition is satisfied. Here's some code to suggest how this works:

λ: Nothing <|> Just 6 <|> Just 7
Just 6
it :: Num a => Maybe a

λ: Nothing <|> Just [1,2] <|> Nothing <|> Just [3,4]
Just [1,2]
it :: Num t => Maybe [t]

Upvotes: 0

chi
chi

Reputation: 116139

Quoting the Snap tutorial

If you’re not familiar with Haskell, you may be wondering about the <|>. It is simply a binary operator that evaluates its first argument, and if it failed, evaluates the second. If the first argument succeeded, then it stops without evaluating the second argument.

The site function uses <|> to connect three different functions that guard what page gets rendered. First, the ifTop function runs. This function succeeds if the requested URL is http:// site.com. If that happens, then Snap sends a response of “hello world”. Otherwise the route function is executed.

Upvotes: 2

J. Abrahamson
J. Abrahamson

Reputation: 74334

It's a method in the Alternative typeclass in the module Control.Applicative in the base package.

Typically it means that you're dealing with a kind of computation which can fail and continue. If both x and y are typed as m a where m tags this kind of computation we're talking about then

x <|> y :: m a

is a computation which "tries" x and if it fails then "tries" y. Such kinds of computation instantiate Alternative.

Upvotes: 9

Related Questions