Callat
Callat

Reputation: 3044

What is the | symbol for in f #?

I'm pretty new to functional programming and I've started looking at the documentation for match statements and in the example I came across here gitpages and cut and pasted to my question below:

let rec fib n =
    match n with
    | 0 -> 0
    | 1 -> 1
    | _ -> fib (n - 1) + fib (n - 2)

I understand that let is for static binding in this case for a recursive function called fib which takes a parameter n. It tries to match n with 3 cases. If it's 0, 1 or anything else.

What I don't understand is what the | symbol is called in this context or why it is used? Anything I search for pertaining to f-sharp pipe takes me to this |> which is the piping character in f sharp.

What is this | used for in this case? Is it required or optional? And when should be and shouldn't I be using |?

Upvotes: 3

Views: 964

Answers (2)

rmunn
rmunn

Reputation: 36738

To expand on Tomas's excellent answer, here are some more of the various uses of | in F#:

Match expressions

In match expressions, | separates the various patterns, as Tomas has pointed. While you can write the entire match expression on a single line, it's conventional to write each pattern on a separate line, lining up the | characters, so that they form a visual indicator of the scope of the match statement:

match n with
| 0 -> "zero"
| 1 -> "one"
| 2 -> "two"
| 3 -> "three"
| _ -> "something else"

Discriminated Unions

Discriminated Unions (or DUs, since that's a lot shorter to type) are very similar to match expressions in style: defining them means listing the possibilities, and | is used to separate the possibilities. As with match expressions, you can (if you want to) write DUs on a single line:

type Option<'T> = None | Some of 'T

but unless your DU has just two possibilities, it's usually better to write it on multiple lines:

type ContactInfo =
    | Email of string
    | PhoneNumber of areaCode : string * number : string
    | Facebook of string
    | Twitter of string

Here, too, the | ends up forming a vertical line that draws the eye to the possibilities of the DU, and makes it very clear where the DU definition ends.

Active patterns

Active patterns also use | to separate the possibilities, but they also are wrapped inside an opening-and-closing pair of | characters:

let (Even|Odd) n   = if n % 2 = 0 then Even else Odd  // <-- Wrong!
let (|Even|Odd|) n = if n % 2 = 0 then Even else Odd  // <-- Right!

Active patterns are usually written in the way I just showed, with the | coming immediately inside the parentheses, which is why some people talk about "banana clips" (because the (| and |) pairs look like bananas if you use your imagination). But in fact, it's not necessary to write the (| and |) characters together: it's perfectly valid to have spaces separating the parentheses from the | characters:

let (|Even|Odd|)   n = if n % 2 = 0 then Even else Odd  // <-- Right!
let ( |Even|Odd| ) n = if n % 2 = 0 then Even else Odd  // <-- ALSO right!

Unrelated things

The pipe operator |> and the Boolean-OR operator || are not at all the same thing as uses of the | operator. F# allows operators to be any combination of symbols, and they can have very different meanings from an operator that looks almost the same. For example, >= is a standard operator that means "greater than". And many F# programs will define a custom operator >>=. But although >>= is not defined in the F# core library, it has a standard meaning, and that standard meaning is NOT "a lot greater than". Rather, >>= is the standard way to write an operator for the bind function. I won't get into what bind does right now, as that's a concept that could take a whole answer all on its own to go through. But if you're curious about how bind works, you can read Scott Wlaschin's series on computation expressions, which explains it all very well.

Upvotes: 5

Tomas Petricek
Tomas Petricek

Reputation: 243096

The | symbol is used for several things in F#, but in this case, it serves as a separator of cases of the match construct.

The match construct lets you pattern match on some input and handle different values in different ways - in your example, you have one case for 0, one for 1 and one for all other values.

Generally, the syntax of match looks like this:

match <input> with <case_1> | ... | <case_n>

Where each <case> has the following structure:

<case> = <pattern> -> <expression>

Here, the | symbol simply separates multiple cases of the pattern matching expression. Each case then has a pattern and an expression that is evaluated when the input matches the pattern.

Upvotes: 6

Related Questions