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).
Related
This is a simple implimentation of factorial function in F#
let rec fact =function
| 0->1
| n-> n * fact(n-1);;
fact 5
1- what is the role of the rec word here?
2- fact is the function, but it is never mentioned that it can have a parameter.
So technically it should face with an error, since in the signature
(let rec fact ) there is no parameter defined for it.
So how does it works?
1) rec is used to mark function as recursive. Without it you would not be able to call it from within the function implementation. Read more on MSDN: Recursive Functions: The rec Keyword (F#)
2) let rec fact = function is a shortcut for:
let rec fact argument =
match argument with
| 0 -> 1
| n -> n * fact (n-1)
As you can see, there is a single parameter which is pattern matched with provided conditions.
It's called a pattern matching function and is described on MSDN: Match Expressions (F#)
I'm trying to write some function that handle errors by returning double options instead of doubles. Many of these functions call eachother, and so take double options as inputs to output other double options. The problem is, I can't do with double options what I can do with doubles--something simple like add them using '+'.
For example, a function that divides two doubles, and returns a double option with none for divide by zero error. Then another function calls the first function and adds another double option to it.
Please tell me if there is a way to do this, or if I have completely misunderstood the meaning of F# option types.
This is called lifting - you can write function to lift another function over two options:
let liftOpt f o1 o2 =
match (o1, o2) with
| (Some(v1), Some(v2)) -> Some(f v1 v2)
| _ -> None
then you can supply the function to apply e.g.:
let inline addOpt o1 o2 = liftOpt (+) o1 o2
liftA2 as mentioned above will provide a general way to 'lift' any function that works on the double arguments to a function that can work on the double option arguments.
However, in your case, you may have to write special functions yourself to handle the edge cases you mention
let (<+>) a b =
match (a, b) with
| (Some x, Some y) -> Some (x + y)
| (Some x, None) -> Some (x)
| (None, Some x) -> Some (x)
| (None, None) -> None
Note that liftA2 will not put the cases where you want to add None to Some(x) in automatically.
The liftA2 method for divide also needs some special handling, but its structure is generally what we would write ourselves
let (</>) a b =
match (a, b) with
| (Some x, Some y) when y <> 0.0d -> Some (x/y)
| _ -> None
You can use these functions like
Some(2.0) <+> Some(3.0) // will give Some(5.0)
Some(1.0) </> Some(0.0) // will give None
Also, strictly speaking, lift is defined as a "higher order function" - something that takes a function and returns another function.
So it would look something like this:
let liftOpt2 f =
(function a b ->
match (a, b) with
| (Some (a), Some (b)) -> f a b |> Some
| _ -> None)
In the end, I realized what I was really looking for was the Option.get function, which simply takes a 'a option and returns an 'a. That way, I can pattern match, and return the values I want.
In this case you might want to consider Nullables over Options, for two reasons:
Nullables are value types, while Options are reference types. If you have large collections of these doubles, using Nullables will keep the numbers on the stack instead of putting them on the heap, potentially improving your performance.
Microsoft provides a bunch of built-in Nullable Operators that do let you directly perform math on nullables, exactly as you're trying to do with options.
I am running into difficulty with F# in numerous scenarios. I believe I'm not grasping some fundamental concepts. I'm hoping someone can track my reasoning and figure out the (probably many) things I'm missing.
Say I'm using Xunit. What I'd like to do is, provided two lists, apply the Assert.Equal method pairwise. For instance:
Open Xunit
let test1 = [1;2;3]
let test2 = [1;2;4]
List.map2 Assert.Equal test1 test2
The compiler complains that the function Equal does not take one parameter. As far as I can tell, shouldn't map2 be providing it 2 parameters?
As a sanity check, I use the following code in f# immediate:
let doequal = fun x y -> printf "result: %b\n" (x = y)
let test1 = [1;2;3]
let test2 = [1;2;4]
List.map2 doequal test1 test2;;
This seems identical. doequal is a lambda taking two generic parameters and returning unit. List.map2 hands each argument pairwise into the lambda and I get exactly what I expected as output:
result: true
result: true
result: false
So what gives? Source shows Xunit.Equal has signature public static void Equal<T>(T expected, T actual). Why won't my parameters map right over the method signature?
EDIT ONE
I thought two variables x and y vs a tuple (x, y) could construct and deconstruct interchangeably. So I tried two options and got different results. It seems the second may be further along than the first.
List.map2 Assert.Equal(test1, test2)
The compiler now complains that 'Successive arguments should be separated spaces or tupled'
List.map2(Assert.Equal(test1, test2))
The compiler now complains that 'A unique overload method could not be determined... A type annotation may be needed'
I think that part of the problem comes from mixing methods (OO style) and functions (FP style).
FP style functions have multiple parameters separated by spaces.
OO style methods have parens and parameters separated by commas.
Methods in other .NET libraries are always called using "tuple" syntax (actually subtly different from tuples though) and a tuple is considered to be one parameter.
The F# compiler tries to handle both approaches, but needs some help occasionally.
One approach is to "wrap" the OO method with an FP function.
// wrap method call with function
let assertEqual x y = Assert.Equal(x,y)
// all FP-style functions
List.map2 assertEqual test1 test2
If you don't create a helper function, you will often need to convert multiple function parameters to one tuple when calling a method "inline" with a lambda:
List.map2 (fun x y -> Assert.Equal(x,y)) test1 test2
When you mix methods and functions in one line, you often get the "Successive arguments should be separated" error.
printfn "%s" "hello".ToUpper()
// Error: Successive arguments should be separated
// by spaces or tupled
That's telling you that the compiler is having problems and needs some help!
You can solve this with extra parens around the method call:
printfn "%s" ("hello".ToUpper()) // ok
Or sometimes, with a reverse pipe:
printfn "%s" <| "hello".ToUpper() // ok
The wrapping approach is often worth doing anyway so that you can swap the parameters to make it more suitable for partial application:
// wrap method call with function AND swap params
let contains searchFor (s:string) = s.Contains(searchFor)
// all FP-style functions
["a"; "b"; "c"]
|> List.filter (contains "a")
Note that in the last line I had to use parens to give precedence to contains "a" over List.filter
public static void Equal<T>(T expected, T actual)
doesn't take two parameters - it takes one parameter, which is a tuple with two elements: (T expected, T actual).
Try this instead:
List.map2 Assert.Equal(test1, test2)
It's all there in the type signatures.
The signature for Assert.Equals is something along the lines of 'a * 'a -> unit. List.map2 expects a 'a -> 'b -> 'c.
They just don't fit together.
List.map2 (fun x y -> Assert.Equal(x,y)) test1 test2 - works because the lambda wrapping Equals has the expected signature.
List.zip test1 test2 |> List.map Assert.Equal - works because you now have a single list of tuples, and since List.map wants an 'a -> 'b function (where 'a is now a tuple), Assert.Equal is now fair game.
It's simply not true that two values and a tuple are implicitly interchangeable. At least not as far as F# the language is concerned, or the underlying IL representation is concerned. You can think that it's that way when you call into F# code from, say, C# - an 'a -> 'b -> 'c function there is indeed called the same way syntactically as an 'a * 'b -> 'c function - but this is more of an exception than a rule.
According to its signature Xunit.Assert.Equal() takes a single 2 values tuple parameter
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
I have a function of the form
'a -> ('a * int) list -> int
let rec getValue identifier bindings =
match bindings with
| (identifier, value)::tail -> value
| (_, _)::tail -> getValue identifier tail
| [] -> -1
I can tell that identifier is not being bound the way I would like it to and is acting as a new variable within the match expression. How to I get identifier to be what is passed into the function?
Ok! I fixed it with a pattern guard, i.e. | (i, value)::tail when i = indentifier -> value
but I find this ugly compared to the way I originally wanted to do it (I'm only using these languages because they are pretty...). Any thoughts?
You can use F# active patterns to create a pattern that will do exactly what you need. F# supports parameterized active patterns that take the value that you're matching, but also take an additional parameter.
Here is a pretty stupid example that fails when the value is zero and otherwise succeeds and returns the addition of the value and the specified parameter:
let (|Test|_|) arg value =
if value = 0 then None else Some(value + arg)
You can specify the parameter in pattern matching like this:
match 1 with
| Test 100 res -> res // 'res' will be 101
Now, we can easily define an active pattern that will compare the matched value with the input argument of the active pattern. The active pattern returns unit option, which means that it doesn't bind any new value (in the example above, it returned some value that we assigned to a symbol res):
let (|Equals|_|) arg x =
if (arg = x) then Some() else None
let foo x y =
match x with
| Equals y -> "equal"
| _ -> "not equal"
You can use this as a nested pattern, so you should be able to rewrite your example using the Equals active pattern.
One of the beauties of functional languages is higher order functions. Using those functions we take the recursion out and just focus on what you really want to do. Which is to get the value of the first tuple that matches your identifier otherwise return -1:
let getValue identifier list =
match List.tryFind (fun (x,y) -> x = identifier) list with
| None -> -1
| Some(x,y) -> y
//val getValue : 'a -> (('a * int) list -> int) when 'a : equality
This paper by Graham Hutton is a great introduction to what you can do with higher order functions.
This is not directly an answer to the question: how to pattern-match the value of a variable. But it's not completely unrelated either.
If you want to see how powerful pattern-matching could be in a ML-like language similar to F# or OCaml, take a look at Moca.
You can also take a look at the code generated by Moca :) (not that there's anything wrong with the compiler doing a lot of things for you in your back. In some cases, it's desirable, even, but many programmers like to feel they know what the operations they are writing will cost).
What you're trying to do is called an equality pattern, and it's not provided by Objective Caml. Objective Caml's patterns are static and purely structural. That is, whether a value matches the pattern depends solely on the value's structure, and in a way that is determined at compile time. For example, (_, _)::tail is a pattern that matches any non-empty list whose head is a pair. (identifier, value)::tail matches exactly the same values; the only difference is that the latter binds two more names identifier and value.
Although some languages have equality patterns, there are non-trivial practical considerations that make them troublesome. Which equality? Physical equality (== in Ocaml), structural equality (= in Ocaml), or some type-dependent custom equality? Furthermore, in Ocaml, there is a clear syntactic indication of which names are binders and which names are reference to previously bound values: any lowercase identifier in a pattern is a binder. These two reasons explain why Ocaml does not have equality patterns baked in. The idiomatic way to express an equality pattern in Ocaml is in a guard. That way, it's immediately clear that the matching is not structural, that identifier is not bound by this pattern matching, and which equality is in use. As for ugly, that's in the eye of the beholder — as a habitual Ocaml programmer, I find equality patterns ugly (for the reasons above).
match bindings with
| (id, value)::tail when id = identifier -> value
| (_, _)::tail -> getValue identifier tail
| [] -> -1
In F#, you have another possibility: active patterns, which let you pre-define guards that concern a single site in a pattern.
This is a common complaint, but I don't think that there's a good workaround in general; a pattern guard is usually the best compromise. In certain specific cases there are alternatives, though, such as marking literals with the [<Literal>] attribute in F# so that they can be matched against.