Negative pattern match - f#

I have the following code (`IgnoreCase is an active pattern I have defined elsewhere):
match myType with
| {Field1 = IgnoreCase "invalid"} -> None
| {Field2 = Some f2
Field3 = Some f3
Field4 = None | Some (0 | 1 | 2)}
-> Some (f2, f3)
| _ -> None
As you can see, Field1 has a blacklisted value and Field4 has whitelisted values (so do Field2 and Field3 in the sense that they must be Some). IMHO it would look slightly cleaner if I could do all checks in the same case, i.e. do the Field1 = IgnoreCase "invalid" match together with the other matches using e.g. Field1 <> IgnoreCase "invalid", but that particular example does not compile. I know about guards, but that does not seem cleaner than the original solution.
Is it possible to do "negative" (logical NOT) pattern matches in the sense that a value should not match some other value, without using guards?

As far as I know, there's no good way to do this. You can see the supported patterns here and verify that there's no construct for negation. One reason for the lack of such a feature might be that it would interact strangely with other pattern matching features (e.g. what would it mean to introduce an identifier with an as pattern inside of a negative context?). And this is not something that you could implement in a general fashion yourself via an active pattern, because an active pattern receives a value, not a pattern expression.

You could define an active pattern called Not:
let (|Not|_|) a b = if a <> b then Some () else None
Then you can use it inside the pattern match:
match myType with
| {Field1 = Not "invalid"
Field2 = Some f2
Field3 = Some f3
Field4 = None | Some (0 | 1 | 2)}
-> Some (f2, f3)
| _ -> None
A limitation of this active pattern is that it must take a literal value, not a sub-pattern. Active patterns aren't composable like the built-in patterns. However, that's also a potential advantage because you can pass it identifiers as values instead of binding a new value to the identifier:
let invalidString = "invalid"
match myType with
| {Field1 = Not invalidString
...

I would use active patterns like this
let (|Check|_|) x =
let = { Field2 = f2; Field3 = f3; Field4 = f4 }
let check =
f4 = None ||
f4 = Some 1 ||
f4 = Some 2 ||
f4 = Some 3
if check then Some (f2, f3) else None
match myType with
| {Field1 = "invalid"} -> None
| Check (x, y) -> Some (x, y)
| _ -> None

Related

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).

In F#, return true if expression matches pattern?

I am looking for a shorter/neater way of doing the equivalent of the following (for any pattern known at compile time):
let f x = match x with | ['A'::_] -> true ; | _ -> false
is there a way of doing this in general, i.e. return true iff an expression matches a given pattern?
You could shorten it slightly using function:
let f = function ['A'::_] -> true | _ -> false
In f#, patterns are not values themselves, and there is no mechanism for converting them to values(*). So, no, there is no neater way.
That said, you may have other options depending on why you're interested in checking whether a pattern matches. Caring about whether a pattern matches but not about which values were matched seems a bit unusual to me, so maybe there's an opportunity for refactoring.
As a simple example, suppose you're doing this:
let t = match e with <pattern> -> true | _ -> false
...
if t then
(* Do something. *)
else
(* Do something else. *)
...
In that case, you could consider instead doing this:
...
match e with
<pattern> -> (* Do something. *)
| _ -> (* Do something else. *)
...
(Supposing the test happens only once, of course.)
(*) Ignoring reflection and quotations.
You may be thinking of an Active Pattern here, specifically its single-case form. It would allow you to create a pattern which returns a boolean value:
let (|F|) = function
| ['A'::_] -> true
| _ -> false
let (F x) = [['A']] // val x : bool = true
The Active Pattern can be parameterized. Of the (n + 1) arguments it accepts, the first n get passed to the syntactic function, and the last argument is the value matched.
let (|G|) e = function
| [d::_] when d = e -> true
| _ -> false
let (G 'A' y) = [['A']] // val y : bool = true

Pattern matching with guards vs if/else construct in F#

In ML-family languages, people tend to prefer pattern matching to if/else construct. In F#, using guards within pattern matching could easily replace if/else in many cases.
For example, a simple delete1 function could be rewritten without using if/else (see delete2):
let rec delete1 (a, xs) =
match xs with
| [] -> []
| x::xs' -> if x = a then xs' else x::delete1(a, xs')
let rec delete2 (a, xs) =
match xs with
| [] -> []
| x::xs' when x = a -> xs'
| x::xs' -> x::delete2(a, xs')
Another example is solving quadratic functions:
type Solution =
| NoRoot
| OneRoot of float
| TwoRoots of float * float
let solve1 (a,b,c) =
let delta = b*b-4.0*a*c
if delta < 0.0 || a = 0.0 then NoRoot
elif delta = 0.0 then OneRoot (-b/(2.0*a))
else
TwoRoots ((-b + sqrt(delta))/(2.0*a), (-b - sqrt(delta))/(2.0*a))
let solve2 (a,b,c) =
match a, b*b-4.0*a*c with
| 0.0, _ -> NoRoot
| _, delta when delta < 0.0 -> NoRoot
| _, 0.0 -> OneRoot (-b/(2.0*a))
| _, delta -> TwoRoots((-b + sqrt(delta))/(2.0*a),(-b - sqrt(delta))/(2.0*a))
Should we use pattern matching with guards to ignore ugly if/else construct?
Is there any performance implication against using pattern matching with guards? My impression is that it seems to be slow because pattern matching has be checked at runtime.
The right answer is probably it depends, but I surmise, in most cases, the compiled representation is the same. As an example
let f b =
match b with
| true -> 1
| false -> 0
and
let f b =
if b then 1
else 0
both translate to
public static int f(bool b)
{
if (!b)
{
return 0;
}
return 1;
}
Given that, it's mostly a matter of style. Personally I prefer pattern matching because the cases are always aligned, making it more readable. Also, they're (arguably) easier to expand later to handle more cases. I consider pattern matching an evolution of if/then/else.
There is also no additional run-time cost for pattern matching, with or without guards.
Both have their own place. People are more used to If/else construct for checking a value where as pattern matching is like a If/else on steroids. Pattern matching allows you to sort of compare against the decomposed structure of the data along with using gaurds for specifying some additional condition on the parts of the decomposed data or some other value (specially in case of recursive data structures or so called discriminated unions in F#).
I personally prefer to use if/else for simple values comparisons (true/false, ints etc), but in case you have a recursive data structure or something which you need to compare against its decomposed value than there is nothing better than pattern matching.
First make it work and make it elegant and simple and then if you seem some performance problem then check for performance issues (which mostly will be due to some other logic and not due to pattern matching)
Agree with #Daniel that pattern matching is usually more flexible.
Check this implementation:
type Solution = | Identity | Roots of float list
let quadraticEquation x =
let rec removeZeros list =
match list with
| 0.0::rest -> removeZeros rest
| _ -> list
let x = removeZeros x
match x with
| [] -> Identity // zero constant
| [_] -> Roots [] // non-zero constant
| [a;b] -> Roots [ -b/a ] // linear equation
| [a;b;c] ->
let delta = b*b - 4.0*a*c
match delta with
| delta when delta < 0.0 ->
Roots [] // no real roots
| _ ->
let d = sqrt delta
let x1 = (-b-d) / (2.0*a)
let x2 = (-b+d) / (2.0*a)
Roots [x1; x2]
| _ -> failwithf "equation is bigger than quadratic: %A" x
Also notice in https://fsharpforfunandprofit.com/learning-fsharp/ that it is discouraged to use if-else. It is considered a bid less functional.
I did some testing on a self writen prime number generator, and as far as i can say there is "if then else" is significantly slower than pattern matching, can't explain why though, but I as far as I have tested the imperativ part of F# have a slower run time than recursive functional style when it come to optimal algorithms.

Conversion between types in discriminated unions

I have a function, which can returns different types, and I use discriminated union for this. What I need, is to have conversion from one type in discriminated union to another type.
Also some of the types can be convertable to all other types (String), but some of the types can be converted only to String (MyCustomType)
For this I've added member method ConvertTo to the ResultType:
type MyTypes =
| Boolean = 1
| Integer = 2
| Decimal = 3
| Double = 4
| String = 5
| MyCustomType = 6
type ResultType =
| Boolean of bool
| Integer of int
| Decimal of decimal
| Double of double
| String of string
| MyCustomType of MyCustomType
with
member this.ConvertTo(newType: MyTypes) =
match this with
| ResultType.Boolean(value) ->
match newType with
| MyTypes.Boolean ->
this
| MyTypes.Integer ->
ResultType.Integer(if value then 1 else 0)
...
| ResultType.MyCustomType(value) ->
match newType with
| MyTypes.MyCustomType ->
this
| MyTypes.String ->
ResultType.String(value.ToString())
| _ ->
failwithf "Conversion from MyCustomType to %s is not supported" (newType.ToString())
I don't like such construction, because if I add more types, this requires me to do many changes: MyTypes, ResultType and also in several places in the ConvertTo member function.
Can anybody suggest better solution for such types conversion?
Thanks in advance
With a slightly different design, it is possible to exploit System.Convert.ChangeType and the fact that the constructors of discriminated unions are actually functions:
// statically typed wrapper for System.Convert.ChangeType
let conv a : 'T = System.Convert.ChangeType(a, typeof<'T>) :?> 'T
type MyCustomType() = class end
type ResultType =
| Boolean of bool
| Integer of int
| Decimal of decimal
| Double of double
| String of string
| MyCustomType of MyCustomType
with
member this.ConvertTo (newType:'T->ResultType) =
match this with
| Boolean b -> newType( conv b )
| Integer i -> newType( conv i )
| Decimal d -> newType( conv d )
| Double d -> newType( conv d )
| String s -> newType( conv s )
| MyCustomType m ->
if typeof<'T> <> typeof<string> then
raise (new System.InvalidCastException("MyCustomType can only be converted to String"))
else
String (m.ToString())
let i = Integer 42
let b = i.ConvertTo Boolean
printfn "%A" b
let d = i.ConvertTo Decimal
printfn "%A" d
let d2 = i.ConvertTo Double
printfn "%A" d2
let s = i.ConvertTo String
printfn "%A" s
//let mi = i.ConvertTo MyCustomType // throws InvalidCastException
let m = MyCustomType (new MyCustomType())
let sm = m.ConvertTo String
printfn "%A" sm
//let im = m.ConvertTo Integer // throws InvalidCastException
EDIT: Once you add more custom types, this will not help much.
Maybe you should make your custom types implement IConvertible. Then you can remove the special case code from ConvertTo and completely rely on System.Convert.ChangeType.
You would still have to extend every custom type's ToObject implementation whenever you add a new custom type. Whether that really is better than a central ConvertTofunction is debatable.
Why are you wanting to do type conversion to begin with? Discriminated Unions are a good way of hiding type information until you need it and abstract complexity away. Generally you have a match statement in a function that consumes this type and then you only cast if you need to.
If you're trying to make some type of parser or language engine then you have no choice but to define all the cast or at least their error states. If you wouldn't mind elaborating on why / what you would use this for, maybe I could suggest another approach.
An aside: F# and .NET in general doesn't support overloading of return types.

F# matching with two values

I'm fairly new to F# and I wanted to compare two values with the (match ... with ...) syntax
The problem arises when I attempt to compare two values like this:
let value1 = 19
let isValue1 y =
match y with
| value1 -> y + 1
| _ -> y
I get a warning that the "| _ -> y" portion of the code will never be reached. Why is this?
I know that I can do the following to get the function to work the way I want it to:
let value1 = 19
let isValue1 y =
match y with
| _ when y = value1 -> true
| _ -> false
This works as well
let value1 = 19
let isValue1 y =
match y with
| 19 -> true
| _ -> false
I'm just curious about why I can't do that, and how match actually works.
The value1 within the match statement is defined as a new variable, the value of which is set to y (as a match). The value1 you define just above is ignored, just as if you were declaring a local variable in a C# function with the same name as a class variable. For this reason, the first match condition will match everything, not just the previously defined value of value1, hence the error. Hope that clarifies matters.
Pattern-matching is both a control construct (what code executes next) and a binding construct (like 'let', bind a name to a value). So when you do
match expr with
| name -> ...
the pattern ("name") always matches and the identifier 'name' just gets bound to the value of the expression. This is why pattern-matching is mostly used with discriminated unions (case types), where you match based on the structure. E.g.
match someOption with
| Some(x) -> ... // binds x
| None -> ...
match someList with
| h :: t -> ... // binds h and t to head/tail
| [] -> ...
You can just match the Input to Literals/Identifiers marked by the [<Literal>] Attribute without binding it.
For Example:
#light
[<Literal>]
let E = 2.718281828459
let isE x =
match x with
| E -> true
| _ -> false
print_any (isE 3.2)
print_any (isE E)
According to Crish Smith

Resources