I understand how active patterns can be defined and used in F#, including partial active patterns, and the different sorts of patterns available. E.g.
let (|Big|Small|) animal = if animal.IsBig then Big(animal) else Small(animal)
let f = function | Big(_) -> "big" |Small(_) -> "small
However, I’m confused regarding using active patterns and discriminated unions in let bindings, arguments, and other places. For example, the MSDN has the following code:
let GetSubstring1 (Slice(p0, p1, text)) =
printfn "Data begins at %d and ends at %d in string %s" p0 p1 text
text.[p0..p1]
Which confuses me a bit.
A specific issue. Let’s say I have the discriminated union,
type Union = A of int * int | B of int
Can I somehow make a function that accepts only Union.A, e.g.
let f (A(a, b)) = a + b
In this situation, it tells me there are unmatched patterns. Is there a way to satisfy it?
As noted by @ildjarn, this applies to all patterns. They can appear in cases of the
matchclause (and infunctionwhich is similar), but also in the parameter declaration ofletbound function and even in theletvalue binding.The key difference is that with
let, you only want to use complete patterns that will always succeed. This is not needed formatchorfunction, because there are multiple clauses, so if the first one fails, the matching can continue and try the next one.For example, the following complete pattern takes
intand returns it as astring:Here are some ways how you can use it:
EDIT: To answer your second question, if you use
letwith an incomplete pattern (i.e. that accepts only a single case of a discriminated union) then you get a compiler warning and the code may fail at runtime (if you call it with the other discriminated union case):If you need to define a function that works only one of the cases, then you need to define a separate type.
Then you can write a function that will only take
AInfo(but you can still work withUnionin places where both options represent a valid input).