Matching tuple elements with "as" pattern - f#

I'd like to convert tuple of two elements having the same type to a list. Code looks simple as this:
let toList (tuple: 'a * 'a): 'a list =
match tuple with
| (_ as fst, _ as snd) -> [fst; snd]
But somehow type of snd is 'a * 'a, so it seems like instead of binding second element of tuple to a variable the whole tuple is bound instead. Is it a bug in compiler or am I missing sth?
Actual code is more complicated, so the idea is not to rewrite the piece provided, but to understand what is wrong with the as usage here. I'd expect that as should go after the tuple to bound it as a whole, like this | (_ as fst, _ as snd) as tuple

For practical purposes #nilekirk's answer is better: you don't need as in this particular case at all.
But if you're wondering why snd has this type for learning purposes, here's an explanation.
Your pattern is compiled like this:
| ((_ as fst, _) as snd) ->
That is, tupling binds stronger than pattern aliasing.
If you want each as to apply to a single element of the tuple, you need to explicitly tell the compiler how to parenthesize them:
| ((_ as fst), (_ as snd)) ->
And incidentally, in F# tuples don't have to be in parens, so the outer parens are not necessary:
| (_ as fst), (_ as snd) ->

The correct syntactic form of the "as" pattern is
pat as ident
This defines ident to be equal to the pattern input and matches the pattern input
against pat.
For your code this means
let toList (tuple: 'a * 'a): 'a list =
match tuple with
| (fst, snd) -> [fst; snd]
where (fst, snd) is a tuple-pattern.
See F# language spec section 7.3 for full details of the "as" pattern.

Related

F# Binary Search Tree

I am trying to implement BST in F#. Since I am starting my journey with F# I wanted to ask for help.
I have simple a test;
[<Fact>]
let ``Data is retained`` () =
let treeData = create [4]
treeData |> data |> should equal 4
treeData |> left |> should equal None
treeData |> right |> should equal None
Tree type which uses discriminated unions
type Tree<'T> =
| Leaf
| Node of value: 'T * left: Tree<'T> * right: Tree<'T>
a recursive function which inserts data nodes into the tree
let rec insert newValue (targetTree: Tree<'T>) =
match targetTree with
| Leaf -> Node(newValue, Leaf, Leaf)
| Node (value, left, right) when newValue < value ->
let left' = insert newValue left
Node(value, left', right)
| Node (value, left, right) when newValue > value ->
let right' = insert newValue right
Node(value, left, right')
| _ -> targetTree
now I have problems with create function. I have this:
let create items =
List.fold insert Leaf items
and resulting error:
FS0001 Type mismatch. Expecting a
''a -> Tree<'a> -> 'a' but given a
''a -> Tree<'a> -> Tree<'a>' The types ''a' and 'Tree<'a>' cannot be unified.
The List.fold documentation shows its type signature as:
List.fold : ('State -> 'T -> 'State) -> 'State -> 'T list -> 'State
Let's unpack that. The first argument is a function of type 'State -> 'T -> 'State. That means it takes a state and an argument of type T, and returns a new state. Here, the state is your Tree type: starting at a basic Leaf, you're building up the tree step by step. Second argument to List.fold is the initial state (a Leaf in this case), and third argument is the list of items of type T to fold over.
Your second and third arguments are correct, but your first argument doesn't line up with the signature that List.fold is expecting. List.fold wants something of type 'State -> 'T -> 'State, which in your case would be Tree<'a> -> 'a -> Tree<'a>. That is, a function that takes the tree as its first parameter and a single item as its second parameter. But your insert function takes the parameters the other way around (the item as the first parameter, and the tree as the second parameter).
I'll pause here to note that your insert function is correct according to the style rules of idiomatic F#, and you should not change the order of its parameters. When writing functions that deal with collections, you always want to take the collection as the last parameter so that you can write something like tree |> insert 5. So I strongly suggest you don't change the order of the arguments your insert function takes.
So if you shouldn't change the order of arguments of your insert function, yet they're in the wrong order to use with List.fold, what do you do? Simple: you create an anonymous function with the arguments flipped around, so that you can use insert with List.fold:
let create items =
List.fold (fun tree item -> insert item tree) Leaf items
Now we'll go one step further and generalize this. It's actually pretty common in F# programming to find that your two-parameter function has the parameters the right way around for most things, but the wrong way around for one particular use case. To solve that problem, sometimes it's useful to create a general-purpose function called flip:
let flip f = fun a b -> f b a
Then you could just write your create function like this:
let create items =
List.fold (flip insert) Leaf items
Sometimes the use of flip can make code more confusing rather than less confusing, so I don't recommend using it all the time. (This is also why there isn't a flip function in the F# standard library: because it's not always the best solution. And because it's trivial to write yourself, its lack in the standard library is not a big deal). But sometimes using flip makes code simpler, and I think this is one of those cases.
P.S. The flip function could also have been written like this:
let flip f a b = f b a
This definition is identical to the let flip f = fun a b -> f b a definition I used in the main example. Do you know why?

Map and pattern matching

I have an assignment here that I'm struggling with:
type multimap<'a,'b when 'a:comparison and 'b:comparison> = MMap of Map<'a, list<'b>>
The assignment states that
We define the canonical representation of a multimap to be the representation where the elements in the
value-lists are ordered.
Declare a function canonical: multimap<'a,'b> -> multimap<'a,'b> when 'a : comparison and 'b : comparison
where canonical m returns the canonical representation of m.
Right now I have:
let toOrderedList (mm:multimap<'a,'b>) =
match mm with
| MMap m ->
I don't know how to pattern match on this. Any help? :3
ok, just to give this an answer the function you are looking for can be written like this:
let cannonical (MMap m) =
m
|> Map.map (fun _ vs -> List.sort vs)
|> MMap
this deconstructs the multimap right in the argument definition (pattern-matching) and then pipes the Map<> m through - sorting the lists with Map.map and finally wrapping it back into mulitmap using the constructor MMap

Trouble with FSharp active patterns

I'm parsing code quotations in FSharp and am building up pattern helpers. All was going well till I tried
let (|BinaryFn|_|) fn (input:Expr) =
function
| SpecificCall fn (_,_,l::r::[]) -> Some(l,r)
| _ -> None
let (|Multiply|_|) x =
function
| BinaryFn <# (*) #> (l,r) -> Some(l,r)
| _ -> None
The intention is to have a generic binary function matcher that returns the ''left'' and the ''right'' and then create specialised binary matchers such as Multiple, Divide and Add and Subtract.
However I get an error on the second pattern that
Error FS0001: Type mismatch. Expecting a
'a -> 'b option
but given a
'a -> 'c -> (Expr * Expr) option
The type ''a option' does not match the type
''b -> (Expr * Expr) option' (FS0001) (Shambolics)
Can somebody please enlighten me on what I should be doing here?
The issue here is that function doesn't only pattern-match the last argument, but also adds an additional argument (function is a combination between of fun and match). Remove the function argument input from the first pattern, and your problem will be solved.

Does this pipe tuple operator already exist* somewhere?

I'm aware of (||>) which does (a' * 'b) -> ('a -> b' -> 'c) -> 'c
But I've been finding this quite useful, and wondered if I was reinventing the wheel:
// ('a * 'a) -> ('a -> 'b) -> ('b * 'b)
let inline (|>>) (a,b) f = (f a, f b)
(*It can happen, I only discovered the ceil function half an hour ago!)
No, it doesn't.
However, you will encounter its variant very often if you use FParsec. Here is the type signature in FParsec documentation:
val (|>>): Parser<'a,'u> -> ('a -> 'b) -> Parser<'b,'u>
I think the library has a very well-designed set of operators which can be generalized for other purposes as well. The list of FParsec operators can be found here.
I did a bit of digging; |>> operator doesn't seem to have built-in Haskell counterpart although it is easy to be defined using Control.Arrow.
The operator you described is essentially the map function for a two-element tuple. The map function, in general has a signature (for some F<'a> which could be seq<'a> or many other types in F# libraries):
map : ('a -> 'b) -> F<'a> -> F<'b>
So, if you define F<'a> as a two element tuple, then your function is actually just map (if you flip the arguments):
type F<'a> = 'a * 'a
let map f (a, b) = (f a, f b)
The operation is not built-in anywhere in the F# library, but it is useful to realize that it actually matches a pattern that is quite common in F# libraries elsewhere (list, seq, array, etc.)
Looking at the Haskell answer referenced by #pad - in principle, Haskell makes it possible to define the same function for all types that support such operations using type classes (so you would write just fmap instead of Seq.map or instead of your TwoElementTuple.map, but it actually does not work for various technical reasons - so Haskellers need to call it differently).
In F#, this is not easily possible to define a single map function for different types, but you can still think of your function as a map for two-element tuples (even if you find it easier to give it a symbolic operator name, rather than the name map.)

Why can't F#'s type inference handle this?

I have a sequence of FileInfo, but I only care about their string names, so I want a sequence of string. At first I tried something like this:
Seq.map (fun fi -> fi.Name) fis
But for some reason, F#'s type inference isn't good enough to allow this, and made me explicitly give a type to "fi":
Seq.map (fun (fi : FileInfo) -> fi.Name) fis
Why is this annotation required? If it is known that fis : seq<FileInfo> and that Seq.map : ('a -> 'b) -> seq<'a> -> seq<'b>, then shouldn't it infer that the type of the lambda expression is FileInfo -> 'b, and then, from fi.Name : string, further infer that its type is FileInfo -> string?
Type inference works left-to-right. This is where the pipeline operator is useful; if you already know the type of 'fis', then write it as
fis |> Seq.map (fun fi -> fi.Name)
and the inference works for you.
(In general, expressions of the form
o.Property
o.Method args
require the type of 'o' to be known a priori; for most other expressions, when a type is not pinned down the inference system can 'float a constraint' along that can be solved later, but for these cases, there are no constraints of the form 'all types with a property named P' or 'all types with a method named M' (like duck typing) that can be postponed and solved later. So you need that info now, or inference fails immediately.)
See also an overview of type inference in F#.

Resources