I came across an oddity in the F# pattern matching syntax today, which can lead to apparent failures in the exhaustivity check.
type Thing =
| This
| That
| Other
let useThing =
function
| This -> "A"
| That -> "A"
| That -> "B" // compiler complains
| Other -> "B"
In the above scenario the compiler helpfully tells me that the second That rule will never be matched. However, if I had tried to make the code a bit more compact and had written
let useThing =
function
| This | That -> "A"
| That | Other -> "B"
I do not get any help from the compiler. I think the reason is that | This | That ->. "A" is not a shortcut for | This -> "A" | That -> "A", even though it looks very much like it is (and I've seen many code samples that treat it as such). Instead, from what I can find, the pipe symbol is used both to separate individual patterns, and also as OR pattern.
This is not a big issue for most DUs, but I encountered the problem when mapping a DU with a large number of cases into another DU with a small number of cases. My attempt to use the shortcut syntax caused a bug.
So my questions are:
Is my interpretation correct?
Is there any workaround apart from listing each pattern on a separate line?
Your interpretation is correct.
By leaving out the actions for the first This and second That you are creating an OR pattern as described in Pattern Matching (F#)
To me this is slightly confusing, too, since the logical 'or' is || in F#.
And while it is easy to see the first bar as new alternative and second bar as or in your formatting it becomes less obvious in
let useThing =
function
| This
| That -> "A"
| That
| Other -> "B"
However the compiler can tell whether a whole pattern is useless but it cannot simplify a pattern.
That | Other has a valid match and is therefore not redundant as considered by the compiler.
You can think of much more involved patterns where it would be not at all clear if parts can be left out or how to simplify them.
Related
I'm wondering about the two syntax for the getters:
type Direction =
| Undefined
| Buy
| Sell
member this.Symbol =
match this with
| Direction.Buy -> '↑'
| Direction.Sell -> '↓'
| Direction.Undefined -> '→'
member this.Symbol2 with get() =
match this with
| Direction.Buy -> '↑'
| Direction.Sell -> '↓'
| Direction.Undefined -> '→'
Is there any practical difference between the first one and the second one?
The IL looks identical, but from the usage standpoint? is one preferred for any reason?
They are identical, yes. In general, prefer the first one. The reason why the second one exists is if you have some special logic to do that isn't just grabbing a value. It's more flexible, but more syntax.
Let's say I'm trying to build a simple Stack in F# as follows:
type Stack =
| Empty
| Stack of String list
(I know I can define it recursively but for this example, let's assume I'd like to have a list in there)
Then I define a push operation like this:
let push item deck =
match deck with
| Empty -> Stack [item]
| Stack d -> Stack (item::d)
But when I reach the pop operation... I'm not having success. I wanted to do something like this:
let pop (Stack d) =
match d with
| h::[] -> h,Empty
| h::t -> h,(Stack t)
For now, let's also try to ignore the fact that I might want a peek/pop pair of operations instead of returning a tuple. What I wanted to try was to write a pop operation which would only accept a Stack which is not empty in the first place.
In other words, I only wanted this function to accept one of the cases of the Discriminated Union. However, I immediately get the warning: "Incomplete pattern matches on this expression. For example, the value 'Empty' may indicate a case not covered by the pattern(s)'.
As expected (after the warning), the following code:
let empty = Empty
let s,st = pop empty
... compiles and fails at run time. I wanted it to fail at compile time.
I'm aware I could use other options for this, such as:
let pop stack =
match stack with
| Empty -> None, Empty
| Stack (h::[]) -> Some h,Empty
| Stack (h::t) -> Some h,(Stack t)
or:
let pop stack =
match stack with
| Empty -> Error "Empty Stack"
| Stack (h::[]) -> Ok (h,Empty)
| Stack (h::t) -> Ok (h,(Stack t))
(and on both of these cases I might not even need the Empty case at all...)
But I was trying to make something more restrictive. So... what am I missing here? Is there a way to achieve what I was attempting? Does it even make any sense to want that?
Think about what you're trying to achieve carefully. Consider the following function:
let foo (s: Stack) = pop s
Should foo compile or should it be rejected? Think about it.
I will assume here that you have already thought about it, and offered the only reasonable answer: the "restriction" that you seek should now apply to foo as well. That is, whoever calls foo must also supply only non-empty stack.
Ok, fair enough. But let's go all the way to the turtles:
let main argv =
printf "Provide directive: "
let s =
match Console.ReadLine() with
| "empty" -> Empty
| _ -> Stack [1; 2; 3]
let p = pop s
0
Now should this program compile or be rejected? Obviously, it depends on the user input. The type of the program depends on runtime values. This is actually an active area of research, and there is a name for it: such program is called Dependently Typed. In plain terms it's when values (may) carry types with them, but unlike .NET RTTI, the compiler has visibility into those types and can prove things about their relationships. Fascinating stuff.
F#, for better or worse, doesn't support dependent types, and probably never will.
Now, I will assume that you're ok with not having dependent types, and would like instead to have your "restriction" only for cases when it is definitely known (at compile time) that the stack is not empty.
If this is the case, then your problem is easily solvable by splitting your DU in two:
type NonEmptyStack<'a> = NonEmptyStack of top: 'a * rest: 'a list
type Stack<'a> = Empty | NonEmpty of NonEmptyStack<'a>
let push item stack =
match stack with
| Empty -> NonEmptyStack (item, [])
| NonEmpty (NonEmptyStack (top, rest)) -> NonEmptyStack (item, top::rest)
let pop (NonEmptyStack (top,rest)) =
match rest with
| i::tail -> (top, Stack (NonEmptyStack (i, tail)))
| _ -> (top, Empty)
Notice how push always returns a non-empty stack, and pop accepts only non-empty stack. The types encode the meaning. This is what they're supposed to do.
The problem lies in your model -- there are two ways to represent an empty stack:
let empty1 = Empty
let empty2 = Stack []
Given this, it's not clear how you want it to behave. This is why I would suggest either going with a recursively defined stack, or or just using a list. Here's your options:
// type alias
type Stack<'a> = 'a list
// single-case DU
type Stack<'a> = Stack of 'a list
// traditional recursive type (which happens to be exactly equivalent to list<'a>)
type Stack<'a> = Empty | Stack of 'a * Stack<'a>
That said, if you really just want to keep it the way you have it right now, and get it to compile, you just need to match the extra "empty" representation:
let pop stack =
match stack with
| Empty | Stack [] -> None, Empty
| Stack (h::[]) -> Some h,Empty
| Stack (h::t) -> Some h,(Stack t)
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 |?
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.
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.
Suppose I have the following DU:
type Something =
| A of int
| B of string * int
Now I use it in a function like this:
let UseSomething = function
| A(i) -> DoSomethingWithA i
| B(s, i) -> DoSomethingWithB s i
That works, but I've had to deconstruct the DU in order to pass it to the DoSomethingWith* functions. It feels natural to me to try to define DoSomethingWithA as:
let DoSomethingWithA (a: Something.A) = ....
but the compiler complains that the type A is not defined.
It seems entirely in keeping with the philosophy of F# to want to restrict the argument to being a Something.A, not just any old int, so am I just going about it the wrong way?
The important thing to note is that A and B are constructors of the same type Something. So you will get inexhaustive pattern matching warning if you try to use A and B cases separately.
IMO, deconstructing all cases of DUs is a good idea since it is type-safe and forces you to think of handling those cases even you don't want to. The problem may arise if you have to deconstruct DUs repetitively in the same way. In that case, defining map and fold functions on DUs might be a good idea:
let mapSomething fa fb = function
| A(i) -> fa i
| B(s, i) -> fb s i
Please refer to excellent Catamorphism series by #Brian to learn about fold on DUs.
That also said that your example is fine. What you really process are string and int values after deconstruction.
You can use Active Patterns to consume two cases separately:
let (|ACase|) = function A i -> i | B _ -> failwith "Unexpected pattern B _"
let (|BCase|) = function B(s, i) -> (s, i) | A _ -> failwith "Unexpected pattern A _"
let doSomethingWithA (ACase i) = ....
but inferred type of doSomethingWithA is still the same and you get an exception when passing B _ to the function. So it's a wrong thing to do IMO.
The other answers are accurate: in F# A and B are constructors, not types, and this is the traditional approach taken by strongly typed functional languages like Haskell or the other languages in the ML family. However, there are other approaches - I believe that in Scala, for example, A and B would actually be subclasses of Something, so you could use those more specific types where it makes sense to do so. I'm not completely sure what tradeoffs are involved in the design decision, but generally speaking inheritance makes type inference harder/impossible (and true to the stereotype type inference in Scala is much worse than in Haskell or the ML languages).
A is not a type, it is just a constructor for Something. There's no way you can avoid pattern matching, which is not necessarily a bad thing.
That said, F# does offer a thing called active patterns, for instance
let (|AA|) = function
| A i -> i
| B _ -> invalidArg "B" "B's not allowed!"
which you can then use like this:
let DoSomethingWithA (AA i) = i + 1
But there's no real reason why you would want to do that! You still do the same old pattern matching under the hood, plus you risk the chance of a runtime error.
In any case, your implementation of UseSomething is perfectly natural for F#.
open System
let random_number_generator = System.Random(int System.DateTime.Now.Ticks) in
let random_number_below n = random_number_generator.Next(n) in
match random_number_below 3 with
| 0 -> "Zero!"
| 1 -> "One!"
| 2 -> "Two!"
;;
The above match statement is not exhaustive, according to the compiler. This is totally legitimate, as F# has no syntactical information that would guarantee the bounds of the random number.
Incomplete pattern matches on this expression. For example, the value '3' may indicate a case not covered by the pattern(s).
What were the idiomatic F# way of matching (or is it simply if-else'ing) against a random number?
As in the comments, solving this in general requires solving the halting problem. As a result the best thing to do is probably
|_ -> failwith "broken RNG"