F# matching expression and 'as' pattern - f#

I'm studying some F# and trying to implement a parser combinator like in this tutorial; after some copy and paste of the proposed solution, I tried to customize it by myself.
Surely there's something I missed but the compiler gives me a weird error message.
type T<'a> =
| A of string
| B of 'a
let foo a b =
match a with
| A s as x -> x
| B i ->
match b with
| A s as x -> x
| B j ->
B (i, j)
The code above is a generalization of the issue I found: the error is notified in the last result (the B branch of the innermost matching expression):
error FS0001: Type mismatch. Expecting a
'a
but given a
'a * 'b
The resulting type would be infinite when unifying ''a' and ''a * 'b'
But if I don't use the as pattern:
let foo a b =
match a with
| A s -> A s // it can also be '| A s as x -> A s'
| B i ->
match b with
| A s -> A s
| B j ->
B (i, j)
then the compiler is happy again.
I don't get why I have to recreate the same logical result if it is already there.

In
A s as x -> x
x has type T<'a> while the required return type for foo is T<('a * 'a)>. Even though the A case does not contain any values of 'a it does not have a polymorphic type like forall 'a . T<'a>. In your second example you are creating a new instance of A which can have the required type.

Related

'Anonymous type variables are not permitted in this declaration' error when adding parameters to discriminated union cases in F#

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

F# recursive type: method vs function type inference differences

Can someone explain please why in F# type-inference seems to work differently (or some other aspect I don't understand?) between class methods and functions.
Imagine the following (simplified):
type Node<'T> = Node2 of 'T * 'T
type Digit<'T> = One of 'T | Two of 'T * 'T
type Tree<'T> =
| Empty
| Single of 'T
| Deep of prefix : Digit<'T> * deeper : Tree<Node<'T>>
with
static member Add (value : 'T) (tree : Tree<'T>) : Tree<'T> =
match tree with
| Empty -> Single value
| Single a -> Deep (One value, Empty)
| Deep (One a, deeper) -> Deep (Two (value, a), deeper)
| Deep (Two (b, a), deeper) -> Deep (One value, deeper |> Tree.Add (Node2 (b, a)))
let rec add (value : 'T) (tree : Tree<'T>) : Tree<'T> =
match tree with
| Empty -> Single value
| Single a -> Deep (One value, Empty)
| Deep (One a, deeper) -> Deep (Two (value, a), deeper)
| Deep (Two (b, a), deeper) -> Deep (One value, deeper |> add (Node2 (b, a)))
Note that static method Add and function add have identical implementation and both call itself recursively.
Yet former compiles fine but latter report an error:
Type mismatch. Expecting a
Tree<Node<'T>> -> Tree<Node<'T>>
but given a
Tree<'T> -> Tree<'T>
The resulting type would be infinite when unifying ''T' and 'Node<'T>'
In the free floating function add, the generic type parameter belongs to the function itself (add<'T>).
However, in the static member function, the type parameter actually belongs to the class (Tree<'T>).
Why does this matter? Because when you refer to the function itself, the compiler assumes that the type parameter is unchanged unless otherwise specified. It won't guess a different one, because that could hide a huge category of type mismatch errors.
However, it doesn't make the same assumption for the type to which the function belongs.
If you check the parameters, the call to add is assumed to be a call to add<'T>, which causes an infinite generic recursion and doesn't compile.
But, the call to Tree.Add is inferred to be a call to Tree<Node<'T>>.Add, not to Tree<'T>.Add. It's a different function call altogether.
If you explicitly annotate the type:
static member Add (value : 'T) (tree : Tree<'T>) : Tree<'T> =
// ...
| Deep (Two (b, a), deeper) -> Deep (One value, deeper |> Tree<'T>.Add (Node2 (b, a)))
you will get the exact same type mismatch / infinite type error as on the free function.
Likewise you get the error if you make it an instance member and refer to the same instance:
member this.Add (value : 'T) (tree : Tree<'T>) : Tree<'T> =
// ...
| Deep (Two (b, a), deeper) -> Deep (One value, deeper |> this.Add (Node2 (b, a)))
Vice-versa, you can make the free function compile by annotating the type parameter, so that the compiler will not assume "it's the same symbol, so must refer to the same value":
let rec add<'T> (value : 'T) (tree : Tree<'T>) : Tree<'T> =
// ...
| Deep (Two (b, a), deeper) -> Deep (One value, deeper |> add (Node2 (b, a)))

Overloading operators in type extensions

Ok, so I'm basically trying to add the bind operator to the option type and it seems that everything I try has some non-obvious caveat that prevent me from doing it. I suspect is has something to do with the limits of the .NET typesystem and is probably the same reason typeclasses can't be implemented in user code.
Anyways, I've attempted a couple of things.
First, I tried just the following
let (>>=) m f = ???
realizing that I want to do different things based on the type of m. F# doesn't allow overloads on function but .NET does allow them on methods, so attempt number two:
type Mon<'a> =
static member Bind(m : Option<'a>, f : ('a -> Option<'b>)) =
match m with
| None -> None
| Some x -> f x
static member Bind(m : List<'a>, f : ('a -> List<'b>)) =
List.map f m |> List.concat
let (>>=) m f = Mon.Bind(m, f)
No dice. Can't pick a unique overload based on previously given type info. Add type annotations.
I've tried making the operator inline but it still gives the same error.
Then I figured I could make the >>= operator a member of a type. I'm pretty sure this would work but I don't think I can hack it in on existing types. You can extend existing types with type Option<'a> with but you can't have operators as extensions.
That was my last attempt with this code:
type Option<'a> with
static member (>>=) (m : Option<'a>, f : ('a -> Option<'b>)) =
match m with
| None -> None
| Some x -> f x
"Extension members cannot provide operator overloads. Consider defining the operator as part of the type definition instead." Awesome.
Do I have any other option? I could define separate functions for different monads in separate modules but that sounds like hell if you want to use more than one version in the same file.
You can combine .NET overload resolution with inline/static constraints in order to get the desired behaviour.
Here's a step by step explanation and here's a small working example for your specific scenario:
type MonadBind = MonadBind with
static member (?<-) (MonadBind, m:Option<'a>, _:Option<'b>) =
fun (f:_->Option<'b>) ->
match m with
| None -> None
| Some x -> f x
static member (?<-) (MonadBind, m:List<'a>, _:List<'b>) =
fun (f:_->List<'b>) ->
List.map f m |> List.concat
let inline (>>=) m f : 'R = ( (?<-) MonadBind m Unchecked.defaultof<'R>) f
[2; 1] >>= (fun x -> [string x; string (x+2)]) // List<string> = ["2"; "4"; "1"; "3"]
Some 2 >>= (fun x -> Some (string x)) // Option<string> = Some "2"
You can also specify the constraints 'by hand', but when using operators they're inferred automatically.
A refinement of this technique (without the operators) is what we use in FsControl to define Monad, Functor, Arrow and other abstractions.
Also note you can use directly Option.bind and List.collect for both bind definitions.
Why do you need to (re-define) "bind"? For starters, Option.bind is already defined.
You can use it for defining a "computational expression builder" (F# name for monadic "do" syntax sugar).
See previous answer.

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.

F# pattern matching problem?

I have a problem when pattern matching with F#. I'm building an F# library and have this so far:
namespace parser
module parse =
let public y = function
| x when x.Contains("hi") -> "HELLO"
| x when x.Contains("hello") -> "HI"
| x -> x
but it gives me error: Error Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved.
Essentially, the compiler doesn't understand that you want the argument to your function to be of type string. Basically, you can NOT invoke instance methods on implicitly declared function arguments. You'll need to use something like the following.
let y (value:string) =
match value when
| x when x.Contains("hi") -> "HELLO"
| x when x.Contains("hello") -> "HI"
| x -> x
Interestingly, if you were not invoking an instance method, but instead using it in some other way (where the type was already known), you would be fine. In other words, suppose a StringUtils module contained a method Has, which took in two strings and performed the same check as Contains; if so, you could use the implicit argument, because the compiler already knows of which type the value must be.
module StringUtils =
let has (word:string) value = word.Contains(value)
module Parse =
let y = function
| x when x |> StringUtils.has "hi" -> "HELLO"
| x when x |> StringUtils.has "hello" -> "HI"
| x -> x
Obviously, in many cases, this sort of thing is unnecessarily verbose. But it demonstrates the larger point about F#'s type inference behavior.
The compiler wants to know the type of x is in your y function so you need to annotate it, like this:
let y (x: string) =
match x with
| x when x.Contains "hi" -> "HELLO"
| x when x.Contains "hello" -> "HI"
| x -> x

Resources