Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overloading + operator in F#

So i have this:

open System
open System.Linq
open Microsoft.FSharp.Collections
type Microsoft.FSharp.Collections.List<'a> with
    static member (+) (First : List<'a>) (Second : List<'a>) =
        First.Concat(Second)

let a = [1; 2; 3; 4; 54; 9]
let b = [3; 5; 6; 4; 54]


for x in List.(+) a b do
    Console.WriteLine(x)

and I want to convert the last line into

for x in a + b do
    Console.WriteLine(x)

but doing so gives me a

The type 'int list' does not support any operands named '+'

The documentation and examples on the web are flakey, and despite my google-fu i have been unable to get it to work. Basically, coming from a python background, I want to get my list manipulation syntax as terse as I am used to: it should not need more than 1 character in infix notation.

like image 639
Li Haoyi Avatar asked Oct 08 '11 07:10

Li Haoyi


2 Answers

Note that @ is already a 1-char infix operator to concat lists.

like image 148
Brian Avatar answered Sep 29 '22 07:09

Brian


Actually there is a way to 're-wire' existing operators, using static constraints and overloads.

type ListExtension = ListExtension with
    static member        (?<-) (ListExtension, a , b) = a @ b
    static member inline (?<-) (ListExtension, a , b) = a + b

let inline (+) a b = (?<-) ListExtension a b

// test

let lst = [1;2] + [3;4]
// val lst : int list = [1; 2; 3; 4]

let sum = 1 + 2 + 3 + 4
// val sum : int = 10

By using the ternary operator the static constraints will be automatically inferred, another option would be to create a method and write the constraints by hand. The first overload cover the case you want to add (lists), the second covers the existing definition.

So now in your code you can do:

for x in (+) a b do
    Console.WriteLine(x)

And that will not break existing (+) for numeric types.

like image 42
Gus Avatar answered Sep 29 '22 06:09

Gus