Given the following active pattern:
let (| HasMatch |) (x:string) =
if x.Contains("0") then Some()
else None;;
And the following pattern matching func:
let testFn x = function
| HasMatch i -> printfn "%A" i
| _ -> printf "nope";;
The last line's wildcard pattern says warning FS0026: This rule will never be matched
All of the examples i see seem to infer that partial active patterns must return Some('a) to match, and that ones that return None get captured by the wildcard. The error seems to say differently.
What am i missing?
I think you should add the None case to the active pattern declaration as follows:
let (| HasMatch | _ |) (x:string) =
if x.Contains("0") then Some()
else None;;
In your orignal example, the compiler infers that you actually want to return the Option type. When you run the printf in your example, you would see it print Some Null when there is a match.
Also, it is bad to return Some(), you should return say Some(x) or similar
Related
I have the following active pattern:
let (|IgnoreCase|_|) (arg: string) (input: string)
if String.Equals(argument, input, StringComparison.OrdinalIgnoreCase)
then Some()
else None
Normally, you would have to use this pattern individually for each case and do something like this:
function
| IgnoreCase "string1"
| IgnoreCase "string2"
What I would like to do is be able to use other matching expressions with the active pattern, for example:
function
| IgnoreCase ("string1" | "string2") // OR pattern
| IgnoreCase ("string1" & "string2") // AND pattern
That returns the error "Invalid argument to parameterized pattern label". I know you can do that using discriminated unions, so it seems like it should be possible using active patterns.
The way you've written the active pattern, it takes a string argument and checks if the input matches the string - this way, there is no way of turning the argument into a pattern itself.
In this particular case, & does not really make sense - but if you just wanted to support |, you could pass a list of arguments:
let (|IgnoreCase|_|) (args: string list) (input: string) =
if args |> List.exists (fun arg ->
String.Equals(arg, input, StringComparison.OrdinalIgnoreCase))
then Some() else None
function
| IgnoreCase ["string1"; "string2"] -> 1
| _ -> 0
If you wanted something more sophisticated, you would need to structure the logic so that the active pattern returns something that can be further matched. One option might be to have pattern that turns the input into lower-case, because then you can specify composed pattern for the lower-cased string:
let (|AsLowerCase|_|) (input: string) =
Some(input.ToLowerInvariant())
function
| AsLowerCase("string1" | "string2") -> 1
| AsLowerCase("string1" & "string2") -> 1
| _ -> 0
This makes the syntax with & syntactically valid, but it will never match. You could however have other patterns like StartsWith and EndsWith so this would then make sense, e.g. to write AsLowerCase(StartsWith "foo" & EndsWith "bar")
So I have some (I'm assuming rather unusual) code which is for building Function Trees. Here's it is right now:
type FunctionTree<'Function> =
| BranchNode of seq<FunctionTree<'Function>>
| Leaf of (a:'Function -> unit) with
member __.Execute() = do a
The expression a:'Function -> unit is what makes the compiler throw a fit, giving me the error 'Anonymous type variables are not permitted in this declaration' and I have no idea why. I've tried adding a variable to the BranchNode, adding (yucky) double parentheses around the expression but nothing seems to have worked.
Answer to the compiler error question
This does not compile...
Leaf of (a:'Function -> unit)
...because discriminated field names can be added to the types of the DU cases, not to the types of the function types in a DU case. In contrast, this compiles...
Leaf of a: ('Function -> unit)
...because the field name a is being used to name the type (Function -> unit).
Additional discussion about the code
However, there is another issue. The member Execute that you are adding is not being added to the Leaf node, as your code implies. It is being added to the entire function tree. Consequently, you will not have access to the label a inside your implementation of Execute. Think of it like this...
type FunctionTree<'Function> =
| BranchNode of seq<FunctionTree<'Function>>
| Leaf of a: ('Function -> unit)
with member __.Execute() = do a
... with the member shifted to the left to clarify that it applies to the entire union, not just the leaf case. That explains why the above code now has a different compiler error... a is not defined. The field name a is used to clarify the instantiation of a Leaf case. The field name a is not available elsewhere.
let leaf = Leaf(a: myFunc)
Consequently, the label a is not available to your Execute member. You would need to do something like this...
with member x.Execute(input) =
match x with
| BranchNode(b) -> b |> Seq.iter(fun n -> n.Execute(input))
| Leaf(f) -> f(input) |> ignore
Notice in the above code that the x value is a FunctionTree.
Alternative implementation
We could continue going. However, I think the following may implement what you are aiming for:
type FunctionTree<'T> =
| BranchNode of seq<FunctionTree<'T>>
| LeafNode of ('T -> unit)
let rec evaluate input tree =
match tree with
| LeafNode(leaf) -> leaf(input)
| BranchNode(branch) -> branch |> Seq.iter (evaluate input)
BranchNode([
LeafNode(printfn "%d")
LeafNode(printfn "%A")
])
|> evaluate 42
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.
I'm learning F# by writing a recursive descent parser using active patterns.
Since all my rules or partial active patterns I need to combine them in different manners, but I'm getting really frustrated with the syntax of passing active patterns as parameters.
The following example shows the trouble I'm having:
// Combines two patterns by chaining them.
let (|Chain|_|) (|Pattern1|_|) (* Should I use pipes here? *) (|Pattern2|_|) data =
match data with
|Pattern1 result ->
match result with
|Pattern2 result2 -> Some result2
|_ -> None
|_ -> None
// Stupid test patterns
let (|IfBiggerThan10ThenDouble|_|) value = if value > 10 then Some (value*2) else None
let (|IfLessThan100ThenDouble|_ |) value = if value < 100 then Some (value*2) else None
match 20 with
// Do I need pipes here?
|Chain (IfBiggerThan10ThenDouble IfLessThan100ThenDouble) value -> printfn "%A" value // Should print 80
| _ -> printfn "Did not match"
My main confusion seems to be about the '|' operator. Sometimes it seems to be a part of the type of the pattern and sometimes part of the name.
You do not really need to implement your own chaining of patterns, because you can directly nest the patterns which gives you the required result:
match 20 with
| IfBiggerThan10ThenDouble(IfLessThan100ThenDouble value) -> printfn "%A" value
| _ -> printfn "Did not match"
This will first call the IfBiggerThan10ThenDouble pattern which calculates 20*2 and passes the value to the nested pattern IfLessThan100ThenDouble. This again doubles the value and binds it to the value symbol (when it succeeds).
That said, your implementation of the Chain pattern actually works and can be called like this:
match 20 with
| Chain (|IfBiggerThan10ThenDouble|_|) (|IfLessThan100ThenDouble|_|) value ->
printfn "%A" value // Should print 80
| _ -> printfn "Did not match"
In general, active pattern (|P|_|) is really just a function with a special name. You can treat it as an ordinary function and call it by writing (|P|_|) argument or you can treat it as a value and pass it as an argument to other functions or parameterized active patterns. Your code would work if you implemented Chain as a pattern taking ordinary functions:
let (|Chain|_|) f g data =
f data |> Option.bind (fun r -> g data)
Then Chain <arg1> <arg2> <pat> is just calling the parameterized active pattern with two functions as an argument. When called, it binds the result to the pattern <pat>. In the above example, the two arguments are function values representing the patterns (these could be ordinary functions, but not lambda functions because of syntactic restrictions).
match value with
| :? list<#SomeType> as l -> l //Is it possible to match any list of a type derived from SomeType?
| _ -> failwith "doesn't match"
As already pointed out, there is no way to do this directly (pattern matching can only bind values, but it cannot bind new type variables). In addition to the (more general) workaround by kvb you can use the fact that all collections implement non-generic IEnumerable, so you can check for this type:
match box value with
| :? System.Collections.IEnumerable as l when
// assumes that the actual type of 'l' is 'List<T>' or some other type
// with single generic type parameter (this is not fully correct, because
// it could be other type too, but we can ignore this for now)
typedefof<SomeType>.IsAssignableFrom
(value.GetType().GetGenericArguments().[0]) ->
l |> Seq.cast<SomeType>
| _ -> failwith "doesn't match"
The code tests whether the value is a non-generic IEnumerable and whether the type parameter is subtype of SomeType. In that case, we got a list of some derived type, so we can cast it to a sequence of SomeType values (this is slightly different than working with list of values of the derived types, but it shouldn't matter for practical purposes).
No, it's unfortunately not possible to do something like this - the CLR doesn't provide any efficient way of doing that kind of type test. See How to cast an object to a list of generic type in F# and F# and pattern matching on generics in a non-generic method implementing an interface for a few (rather ugly) solutions.
I later needed something similar for matching Lazy instances. Here's my solution, in case anyone finds it helpful.
let (|Lazy|_|) (value : obj) =
if box value <> null then
let typ = value.GetType()
if typ.IsGenericType && typ.GetGenericTypeDefinition() = typedefof<Lazy<_>> then
Some(typ.GetGenericArguments().[0])
else None
else None
Usage:
match value with
| Lazy typ when typeof<SomeType>.IsAssignableFrom(typ) -> (value :?> Lazy<_>).Value
| _ -> failwith "not an instance of Lazy<#SomeType>"
According to the F# 2.0 specification, par. 14.5.2 (Solving Subtype Constraints), it will not work, because: "F# generic types do not support covariance or contravariance."
Not the cleanest, but effective:
let matchType<'T> () =
try
let o = Activator.CreateInstance<'T> ()
match box o with
| :? Type1 -> printfn "Type1"
| :? Type2 -> printfn "Type2"
| _ -> failwith "unknown type"
with
| ex -> failwith "%s" (ex.ToString())