Is a wildcard always required for union cases of Active Patterns? - f#

Is a wildcard always required for union cases of Active Patterns?
Warning:
Incomplete pattern matches on this expression.
let (|Positive|Neutral|Negative|) = function
| x when x > 0 -> Positive
| x when x = 0 -> Neutral
| x when x < 0 -> Negative
The warning is resolved when I insert a wild card as a union case:
let (|Positive|Neutral|Negative|) = function
| x when x > 0 -> Positive
| x when x = 0 -> Neutral
| x when x < 0 -> Negative
| _ -> failwith "unknown"
What other cases am I missing?

when guards can't be checked (in general) by the compiler. In this particular case though, just leave out the last guard as you are not missing a case:
let (|Positive|Neutral|Negative|) = function
| x when x > 0 -> Positive
| x when x < 0 -> Negative
| _ -> Neutral
Note: for int, this is OK, floats need a few cases more (NaN and infinity) and the compiler won't help you there (as you just discovered).

Related

F# unable to catch DivideByZeroException

I atempt to catch an exception when dividing by 0 is performed but, no mater the implementation, code shows nothing of substance, always claiming that the result is "infinity" (meaning, from what I get, that it just performed the division and ignored everything else)
What is the reason for this and how to remedy it?
open System
type instruction =
| ADD
| SUB
| MUL
| SQR
| DIV
| PUSH of float
type stack = float list
exception BLEDNY_PROGRAM of (instruction * stack)
exception DivideByZeroException
let intInstr (x, y) =
match x, y with
| ADD, a::b::ys -> (b + a) :: ys : stack
| SUB, a::b::ys -> (b-a)::ys
| MUL, a::b::ys -> (b*a)::ys
| SQR, a::ys -> (a * a)::ys
| DIV, a::b::ys -> try (b/a)::ys with | :? System.DivideByZeroException -> (printf "Błąd: dzielenie przez zero"; ys)
| PUSH x, ys -> x::ys
| _ , _ -> raise (BLEDNY_PROGRAM(x, y));
let intpProg(is) =
let rec iPS = function
| ([],x::xs) -> x
| (i::is, xs) -> iPS(is, intInstr(i, xs))
iPS(is,[])
let il3 = [PUSH 3.0; PUSH 0.0; DIV];
let e = intpProg(il3)
printfn "%A" e
A float in F# is a 64-bit IEEE 754 double-precision number. They have well-defined values for ±zero, ±infinity, and NaN.
For all floating point divisions by zero (except decimal), a DivideByZeroException is not thrown, but rather, the type's special representation is used.
> let ``+∞``, ``-∞`` = 1.0 / 0.0, -1.0 / 0.0;;
val ( -∞ ) : float = -infinity
val ( +∞ ) : float = infinity
In your example, dividing by zero would give you Double.PositiveInfinity.
Integer values (int, long, uint, etc.,) all throw a divide by zero as you'd expect.

Can one set default values for Discriminated Union types?

I implemented a Discriminated Union type that would be used to select a function:
type BooleanCombinator =
| All
| Some
| None
| AtLeast of int
| MoreThan of int
| NotMoreThan of int
| LessThan of int
| ExactlyOne
| ExactlyTwo
| AllButOne
| AllButTwo
let boolToInt (b: bool) : int = if b then 1 else 0
let combineBooleans (combinator : BooleanCombinator)
(bools : bool list)
: bool =
let n = List.sumBy boolToInt bools
match combinator with
| BooleanCombinator.All -> List.forall id bools
| BooleanCombinator.Some -> bools |> List.exists id
| BooleanCombinator.None -> bools |> List.exists id |> not
| BooleanCombinator.AtLeast i -> n >= i
| BooleanCombinator.MoreThan i -> n > i
| BooleanCombinator.NotMoreThan i -> n <= i
| BooleanCombinator.LessThan i -> n < i
| BooleanCombinator.ExactlyOne -> n = 1
| BooleanCombinator.ExactlyTwo -> n = 2
| BooleanCombinator.AllButOne -> n = bools.Length - 1
| BooleanCombinator.AllButTwo -> n = bools.Length - 2
This looked Ok to me but the compiler started to look at all instances of Some and None as belonging to this DU, instead of the Option DU.
I do not want to go through all of my code replacing Some with Option.Some and None with Option.None.
Is there a way to tell the compiler that unqualified Some and None are actually Option.Some and Option.None?
Or should I just give different names to these DU cases, like AtLeastOne and ExactlyZero
The general rule for resolving name collisions in F# is "last declaration wins". Because your custom DU is declared after Option, its constructors Some and None win over those of Option.
But this rule offers a way to fix the problem: you just need to "reassert" the declarations after your custom DU:
type Bogus = Some of int | None
let g = function Some _ -> 42 | None -> 5
let x = Some 42
let inline Some a = Option.Some a
let inline None<'a> = Option.None : 'a option
let (|Some|None|) = function | Option.Some a -> Some a | Option.None -> None
let f = function Some _ -> 42 | None -> 5
let y = Some 42
If you inspect the types of g, x, f, and y in the above code:
> g
g : Bogus -> int
> f
f : 'a option -> int
> x
Bogus
> y
int option
The function g and value x were inferred to have type Bogus -> int and Bogus respectively, because Some and None in their bodies refer to Bogus.Some and Bogus.None.
The function f and value y were inferred to have Option-related types, because Some and None in their bodies refer to the Some function and the (|Some|None|) active pattern that I defined just above.
Of course, this is a rather hacky way to restore status quo. This will convince the compiler, but humans will still have a hard time reading your code. I suggest you rename the cases of your DU instead.
You can mark your DU with [<RequireQualifiedAccess>] attribute.
This means that you will be required to qualify the case name with the type whenever you use it in the code - which is something you do now anyway in your match expression.
That way an unqualified Some would still be resolved to mean Option.Some, despite the fact that you reuse the name.
It's a useful technique to know when you want to use a snappy name for a DU case - like None, Yes, Failure etc. - that by itself would be ambiguous or confusing to the reader (or the compiler, for that matter).

Do I have to use an explicit match statement to identify its wildcard value?

Do I have to use an explicit match statement to identify its wildcard value?
For example, take the following function:
let (|Positive|Neutral|Negative|) = function
| x when x > 0 -> Positive
| x when x = 0 -> Neutral
| x when x < 0 -> Negative
| _ -> failwith (sprintf "unknown: %d" _)
Error:
Unexpected symbol '_' in expression
I learned that I can do this without any errors:
let (|Positive|Neutral|Negative|) v =
match v with
| x when x > 0 -> Positive
| x when x = 0 -> Neutral
| x when x < 0 -> Negative
| _ -> failwith (sprintf "unknown: %d" v)
UPDATE
Here's the result from a posted answer:
let (|Positive|Neutral|Negative|) = function
| x when x > 0 -> Positive
| x when x = 0 -> Neutral
| x when x < 0 -> Negative
| x -> failwith (sprintf "unknown: %d" x)
You can change it to this and it will work:
let (|Positive|Neutral|Negative|) = function
| x when x > 0 -> Positive
| x when x = 0 -> Neutral
| x when x < 0 -> Negative
| f -> failwith (sprintf "unknown: %d" f)

How to handle negative power in F#?

I'm trying to build the nth power function in F#. (Yes, there's already Math.Pow in .Net). Here is my attempt:
let rec nthPower x n =
match n with
| 0 -> 1
| _ -> x * (nthPower x (n-1))
This works fine when n >= 0; however, I don't know how to handle the negative case: when n < 0.
Question:
How to handle the negative case? (n<0)
Is this recursive algorithm efficient? or are there any efficient ways in F#?
You can implement it like this:
let rec nthPower x n =
match n with
| 0 -> 1m
| t when t < 0 -> 1m / (nthPower x -n)
| _ -> decimal x * (nthPower x (n - 1));;
The t when t < 0 allows the pattern matching to match a range of values. I would say that the RHS of this line is self-explanatory, but let me know if it's unclear.
Regarding question #2, I don't think there's anything particularly inefficient about this approach and there's probably not a much simpler way to do it. I'm not sure what the most efficient approach is, but hopefully some mathematicians can chime in.
Edit: I have found an approach that is more efficient for exponents > ~10. It uses memoization and divide-and-conquer to compute the result in O(log n) time instead of O(n):
let rec nthPower x n =
match n with
| 0 -> 1.0
| 1 -> double x
| t when t < 0 -> 1.0 / (nthPower x -n)
| _ ->
let p = nthPower x (n / 2)
p * p * nthPower x (n % 2)

OR pattern matching

I'm trying to use an OR pattern, as described here:
let foo = function
| Some (0, x) when x > 0 | None -> "bar"
| _ -> "baz"
However, this gives a compiler error:
error FS0010: Unexpected symbol '|' in pattern matching. Expected '->'
or other token.
What am I doing wrong? Does it have to do with the when guard?
A when guard refers to a single case, regardless of how many patterns are combined. The cases need to be separated:
let foo = function
| Some (0, x) when x > 0 -> "bar"
| None -> "bar"
| _ -> "baz"
For that reason, it may be better to factor out the return value, so a possibly complex expression isn't repeated:
let foo value =
let ret = "bar"
match value with
| Some (0, x) when x > 0 -> ret
| None -> ret
| _ -> "baz"
Using an active pattern is another way to avoid such repetition:
let (|Bar|_|) = function
| Some(0, x) when x > 0 -> Some()
| None -> Some()
| _ -> None
let foo = function
| Bar -> "bar"
| _ -> "baz"
You'll need two separate match cases there because the two cases bind different sets of variables (x and nothing, respectively):
| Some(0, x) when x>0 -> "bar"
| None -> "bar"
A nice trick I sometime use when you want to guard only specific bindings of a label, in a very complex pattern, is to use my own active patterns and the & (and) pattern operator:
let (|GreaterThan|_|) lowerLimit n =
if n > lowerLimit then Some () else None
let (|LesserThan|_|) upperLimit n =
if n < upperLimit then Some () else None
let (|GreaterOETo|_|) lowerLimit n =
if n >= lowerLimit then Some () else None
let (|LesserOETo|_|) upperLimit n =
if n <= upperLimit then Some () else None
let (|InRange|_|) (lowerLimit, upperLimit) n =
if n >= lowerLimit && n <= upperLimit then Some () else None
let (|Even|Odd|) n =
if n % 2 = 0 then
Even (n / 2)
else
Odd (n / 2)
type Union =
| A of int
| B of int
| A' of int
let getSpecialCases = function
| A (Even (x & GreaterThan 4 & LesserOETo 16))
| A (Odd (x & GreaterThan 0))
| B (x & LesserOETo 0)
| A' (Even (x & InRange (5, 16)))
| A' (Odd (x & GreaterThan 0)) -> Some x
| _ -> None
And of course you can just make a function to active pattern wrapper:
let (|P|_|) pred x =
if pred x then Some () else None
let ``match`` = function
| Even (x & pred (fun x -> x >= 7 && x <= 54)) -> Some x
| _ -> None

Resources