by Nicolas Wu

Posted on 1 August 2011

Tags: Haskell

A recent reddit post asking for a library of conditional one-liners and combinators reminded me of one of my favourite operators: the conditional choice. Most programmers are used to the so-called McCarthy conditional:

`if p then x else y`

An alternative way of viewing this is as a ternary operator:

`x <| p |> y`

This operator is known as the *conditional choice*, but I’m told that it was introduced by Tony Hoare, so maybe naming it the Hoare conditional would make more sense (it makes an appearance in Hoare’s work on Communicating Sequential Processes and Unifying Theories of Programming, but I haven’t found any references to its original introduction).

Rendering conditonals as ternary operators makes it clear that there are a number of nice properties that hold true:

Idempotency

`x <| p |> x == x`

Left-Identity

`x <| True |> y == x`

Right-Identity

`x <| False |> y == y`

Left-Distributivity

`x <| p |> (y <| q |> z) == (x <| p |> y) <| q |> (x <| p |> z)`

Right-Distributivity

`(x <| p |> y) <| q |> z == (x <| q |> z) <| p |> (y <| q |> z)`

Symmetry

`x <| p |> y == y <| not p |> x`

Conjunction-Associativity

`(x <| p |> y) <| q |> z == x <| p && q |> (y <| q |> z)`

Disjunction-Associativity

`x <| p |> (y <| q |> z) == (x <| p |> y) <| p || q |> z`

Conjunction-Collapse

`x <| p |> (y <| p && q |> z) == x <| p |> z`

Disjunction-Collapse

`(x <| p || q |> y) <| q |> z == x <| q |> z`

Abiding (Interchange)

`x # y <| p |> v # w == (x <| p |> v) # (y <| p |> w)`

These laws are easily proved by considering the cases where `p`

and `q`

are `True`

and `False`

.

In Haskell, implementing this operator is quite simple. First we’ll define the right bracket, which takes a predicate and a value `x`

, and returns `Nothing`

if the predicate is `True`

, and returns `Just x`

when it is `False`

:

```
> (|>) :: Bool -> a -> Maybe a
> True |> _ = Nothing
> False |> y = Just y
```

The left bracket is equivalent to `fromMaybe`

, where the resulting value from the application of the right bracket (which evaluates the predicate) is consumed. If the result was `Nothing`

, then we use the value `x`

, otherwise we have `Just y`

, and return `y`

as the result.

```
> (<|) :: a -> Maybe a -> a
> x <| Nothing = x
> _ <| Just y = y
```

Finally we give the operators low infixity precedence, and make them right associative:

```
> infixr 0 <|
> infixr 0 |>
```

Defining the operator this way makes the ternary operator right associative, so that:

`x <| p |> y <| q |> z == x <| p |> (y <| q |> z)`

Right associativity here is useful so that reading from left to right, the result is the expression to the left of the first predicate that is true.