Overloading operators in type extensions - f#

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.

Related

Make Fish in F#

The Kleisli composition operator >=>, also known as the "fish" in Haskell circles, may come in handy in many situations where composition of specialized functions is needed. It works kind of like the >> operator, but instead of composing simple functions 'a -> 'b it confers some special properties on them possibly best expressed as 'a -> m<'b>, where m is either a monad-like type or some property of the function's return value.
Evidence of this practice in the wider F# community can be found e.g. in Scott Wlaschin's Railway oriented programming (part 2) as composition of functions returning the Result<'TSuccess,'TFailure> type.
Reasoning that where there's a bind, there must be also fish, I try to parametrize the canonical Kleisli operator's definition let (>=>) f g a = f a >>= g with the bind function itself:
let mkFish bind f g a = bind g (f a)
This works wonderfully with the caveat that generally one shouldn't unleash special operators on user-facing code. I can compose functions returning options...
module Option =
let (>=>) f = mkFish Option.bind f
let odd i = if i % 2 = 0 then None else Some i
let small i = if abs i > 10 then None else Some i
[0; -1; 9; -99] |> List.choose (odd >=> small)
// val it : int list = [-1; 9]
... or I can devise a function application to the two topmost values of a stack and push the result back without having to reference the data structure I'm operating on explicitly:
module Stack =
let (>=>) f = mkFish (<||) f
type 'a Stack = Stack of 'a list
let pop = function
| Stack[] -> failwith "Empty Stack"
| Stack(x::xs) -> x, Stack xs
let push x (Stack xs) = Stack(x::xs)
let apply2 f =
pop >=> fun x ->
pop >=> fun y ->
push (f x y)
But what bothers me is that the signature val mkFish : bind:('a -> 'b -> 'c) -> f:('d -> 'b) -> g:'a -> a:'d -> 'c makes no sense. Type variables are in confusing order, it's overly general ('a should be a function), and I'm not seeing a natural way to annotate it.
How can I abstract here in the absence of formal functors and monads, not having to define the Kleisli operator explicitly for each type?
You can't do it in a natural way without Higher Kinds.
The signature of fish should be something like:
let (>=>) (f:'T -> #Monad<'U>``) (g:' U -> #Monad<'V>) (x:'T) : #Monad<'V> = bind (f x) g
which is unrepresentable in current .NET type system, but you can replace #Monad with your specific monad, ie: Async and use its corresponding bind function in the implementation.
Having said that, if you really want to use a generic fish operator you can use F#+ which has it already defined by using static constraints. If you look at the 5th code sample here you will see it in action over different types.
Of course you can also define your own, but there is a lot of things to code, in order to make it behave properly in most common scenarios. You can grab the code from the library or if you want I can write a small (but limited) code sample.
The generic fish is defined in this line.
I think in general you really feel the lack of generic functions when using operators, because as you discovered, you need to open and close modules. It's not like functions that you prefix them with the module name, you can do that with operators as well (something like Option.(>=>)) , but then it defeats the whole purpose of using operators, I mean it's no longer an operator.

What is the typical definition/meaning of this F# operator <*>

Being relatively new to functional programming, I am still unfamiliar with all the standard operators. The fact that their definition is allowed to be arbitrary in many languages and also that such definitions aren't available in nearby source code, if at all, makes reading functional code unnecessarily challenging.
Presently, I don't know what <*> as it occurs in WebSharper.UI.Next documentation.
It would be good if there was a place that listed all the conventional definition for the various operators of the various functional languages.
I agree with you, it would be good to have a place where all implicit conventions for operators used in F# are listed.
The <*> operator comes from Haskell, it's an operator for Applicative Functors, its general signature is: Applicative'<('A -> 'B)> -> Applicative'<'A> -> Applicative'<'B> which is an illegal signature in .NET as higher kinds are not supported.
Anyway nothing stops you from defining the operator for a specific Applicative Functor, here's the typical definition for option types:
let (<*>) f x =
match (f, x) with
| Some f, Some x -> Some (f x)
| _ -> None
Here the type is inferred as:
val ( <*> ) : f:('a -> 'b) option -> x:'a option -> 'b option
which is equivalent to:
val ( <*> ) : f: option<('a -> 'b)> -> x: option<'a> -> option<'b>
The intuitive explanation is that it takes a function in a context and an argument for that function in the context, then it executes the function inside the context.
In our example for option types it can be used for applying a function to a result value of an operation which may return a None value:
let tryParse x =
match System.Int32.TryParse "100" with
| (true, x) -> Some x
| _ -> None
Some ((+) 10) <*> tryParse "100"
You can take advantage of currying and write:
Some (+) <*> tryParse "100" <*> Some 10
Which represents something like:
(+) (System.Int32.Parse "100") 10
but without throwing exceptions, that's why it is also said that Applicatives are used to model side-effects, specially in pure functional languages like Haskell. Here's another sample of option applicatives.
But for different types it has different uses, for lists it may be used to zip them as shown in this post.
In F# it's not defined because .NET type system would not make it possible to define it in a generic way however it would be possible using overloads and static member constraints as in FsControl otherwise you will have to select different instances by hand by opening specific modules, which is the approach used in FSharpx.
Just discovered elsewhere in the documentation on another subject...
let ( <*> ) f x = View.Apply f x
where type of View.Apply and therefore ( <*> ) is:
View<'A * 'B> -> View<'A> -> View<'B>

constrain generic type to inherit a generic type in f#

let mapTuple f (a,b) = (f a, f b)
I'm trying to create a function that applies a function f to both items in a tuple and returns the result as a tuple. F# type inference says that mapTuple returns a 'b*'b tuple. It also assumes that a and b are of the same type.
I want to be able to pass two different types as parameters. You would think that wouldn't work because they both have to be passed as parameters to f. So I thought if they inherited from the same base class, it might work.
Here is a less generic function for what I am trying to accomplish.
let mapTuple (f:Map<_,_> -> Map<'a,'b>) (a:Map<int,double>,b:Map<double, int>) = (f a, f b)
However, it gives a type mismatch error.
How do I do it? Is what I am trying to accomplish even possible in F#?
Gustavo is mostly right; what you're asking for requires higher-rank types. However,
.NET (and by extension F#) does support (an encoding of) higher-rank types.
Even in Haskell, which supports a "nice" way of expressing such types (once you've enabled the right extension), they wouldn't be inferred for your example.
Digging into point 2 may be valuable: given map f a b = (f a, f b), why doesn't Haskell infer a more general type than map :: (t1 -> t) -> t1 -> t1 -> (t, t)? The reason is that once you include higher-rank types, it's not typically possible to infer a single "most general" type for a given expression. Indeed, there are many possible higher-rank signatures for map given its simple definition above:
map :: (forall t. t -> t) -> x -> y -> (x, y)
map :: (forall t. t -> z) -> x -> y -> (z, z)
map :: (forall t. t -> [t]) -> x -> y -> ([x], [y])
(plus infinitely many more). But note that these are all incompatible with each other (none is more general than another). Given the first one you can call map id 1 'c', given the second one you can call map (\_ -> 1) 1 'c', and given the third one you can call map (\x -> [x]) 1 'c', but those arguments are only valid with each of those types, not with the other ones.
So even in Haskell you need to specify the particular polymorphic signature you want to use - this may be a bit of a surprise if you're coming from a more dynamic language. In Haskell, this is relatively clean (the syntax is what I've used above). However, in F# you'll have to jump through an additional hoop: there's no clean syntax for a "forall" type, so you'll have to create an additional nominal type instead. For example, to encode the first type above in F# I'd write something like this:
type Mapping = abstract Apply : 'a -> 'a
let map (m:Mapping) (a, b) = m.Apply a, m.Apply b
let x, y = map { new Mapping with member this.Apply x = x } (1, "test")
Note that in contrast to Gustavo's suggestion, you can define the first argument to map as an expression (rather than forcing it to be a member of some separate type). On the other hand, there's clearly a lot more boilerplate than would be ideal...
This problem has to do with rank-n types which are supported in Haskell (through extensions) but not in .NET type system.
One way I found to workaround this limitation is to pass a type with a single method instead of a function and then define an inline map function with static constraints, for example let's suppose I have some generic functions: toString and toOption and I want to be able to map them to a tuple of different types:
type ToString = ToString with static member inline ($) (ToString, x) = string x
type ToOption = ToOption with static member ($) (ToOption, x) = Some x
let inline mapTuple f (x, y) = (f $ x, f $ y)
let tuple1 = mapTuple ToString (true, 42)
let tuple2 = mapTuple ToOption (true, 42)
// val tuple1 : string * string = ("True", "42")
// val tuple2 : bool option * int option = (Some true, Some 42)
ToString will return the same type but operating with arbitrary types. ToOption will return two Generics of different types.
By using a binary operator type inference creates the static constraints for you and I use $ because in Haskell it means apply so a nice detail is that for haskellers f $ x reads already apply x to f.
At the risk of stating the obvious, a good enough solution might be to have a mapTuple that takes two functions instead of one:
let mapTuple fa fb (a, b) = (fa a, fb b)
If your original f is generic, passing it as fa and fb will give you two concrete instantiations of the function with the types you're looking for. At worst, you just need to pass the same function twice when a and b are of the same type.

Why is F# type inference not working in this case

In following case
let a = [1]
let f x = x
let b = a |> List.map f
a is an int list. We call List.map so for sure f must be a int->? function. Why is f still typed as 'a ->'a instead of int->int?
If this is how type inference (not)works in F# i see little benefits for it.
Is there an workaround without specifying the type for x in f explicitly?
Lets imagine x has type (A*B*C list ( D option, E list)))
Also another interesting thing:
open System.Collections.Generic
let d = new Dictionary()
d.[1] ="a"
This does not work unless the "new" keyword is removed.
Type inferencing works just fine here. f is inferred as having the type 'a -> 'a, which means that it'll take a value of the generic type 'a and return a value of the same generic type 'a.
In this case, type inferencing kicks in when you use it. Because a has the type int list, and because List.map has the signature ('T -> 'U) -> 'T list -> 'U list, it can infer types from the expression
let b = a |> List.map f
In this case, the 'T list argument is a, so it has the type int list. This means it now knows that 'T is int.
The function passed to List.map has the general form 'T -> 'U, but in this case we pass f, which has the form 'a -> 'a, which is equivalent to 'T -> 'T. Because of this, the compiler understands that in this case, 'T and 'U are the same types.
This means that it can infer that the return type 'U list must also be int list.
The function f is typed 'a -> 'a because it works at every type, not just int:
> f "foo";;
val it = "foo" : string
> f 0.8;;
val it = 0.8 : float
This an advantage: the generic type 'a -> 'a gives you the freedom to use f when it is safe to do so, as opposed to only at the type int -> int.
To add a little something to the fine answers already listed here.
There is one circumstance where you will want to not use the generic inferred type. The generic version of f will be slower than the type specific version. But F# has a keyword for taking care of that for you:
let inline f x = x
Which tells the compiler to use the type specific version of any operations you apply to x. The inferred type will remain generic. You will only need this in time critical section of code.
As noted elsewhere, the generic inference is a useful thing and you'll probably grow to like it.

Global operator overloading in F#

I'm starting down the road of defining my own operators for Cartesian products and matrix multiplication.
With matrices and vectors aliased as lists:
type Matrix = float list list
type Vector = float list
I can write my own initialisation code (and get a Cartesian product into the bargain) by writing
let inline (*) X Y =
X |> List.collect (fun x -> Y |> List.map (fun y -> (x, y)))
let createVector size f =
[0..size - 1] |> List.map (fun i -> f i)
let createMatrix rows columns f =
[0..rows - 1] * [0..columns - 1] |> List.map (fun i j -> f i j)
So far so good. The problem is that my definition of * wipes out the normal definition, even though my version is only defined for Lists, which don't have their own multiplication operator.
The documentation http://msdn.microsoft.com/en-us/library/vstudio/dd233204.aspx states that "newly defined operators take precedence over the built-in operators". However, I wasn't expecting all of the numerical incarnations to be wiped out -- surely static typing would take care of this?
I know it is possible to define a global operator that respects types, because MathNet Numerics uses * for matrix multiplication. I would also like to go down that road, which would require the typing system to prioritise matrix multiplication over the Cartesian product of Matrix types (which are themselves lists).
Does anyone know how to do this in F#?
Here is the (non idiomatic) solution:
type Mult = Mult with
static member inline ($) (Mult, v1: 'a list) = fun (v2: 'b list) ->
v1 |> List.collect (fun x -> v2 |> List.map (fun y -> (x, y))) : list<'a * 'b>
static member inline ($) (Mult, v1:'a ) = fun (v2:'a) -> v1 * v2 :'a
let inline (*) v1 v2 = (Mult $ v1) v2
The idiomatic solution is to define Matrix as a new type and add operators as static members:
type Matrix =
| MatrixData of float list list
static member (*) (MatrixData m1, MatrixData m2) = (...)
Operators defined using let are useful when you know that the definition does not conflict with anything else, or when you're defining the operator locally in a small scope (within a function).
For custom types, it is a good idea to define operators as static members. Another benefit of this approach is that your type will be usable from C# (including the operators).
To do this in your example, I had to change the type definition from type alias (which is not a stand-alone type and so it cannot have its own static members) to a single-case discriminated union, which can have members - but this is probably a good idea anyway.

Resources