user483036
user483036

Reputation:

how to override tostring on built in collection

How do I override tostring function on a built in collection such as map or sequence such that printfn will use this new custom tostring function?

I would guess it should be something like

type seq<'T> with
    override xs.Tostring() =
        "blabla"

however this just gives the error "type abbreviations cannot have augmentations".

I then looked at msdn and found following about type extension http://msdn.microsoft.com/en-us/library/dd233211.aspx

it states that I should be able to extend for example int32 and sequence like following

type System.Int32 with 
    member this.FromString( s : string ) =
       System.Int32.Parse(s)

type seq<'T> with
    /// Repeat each element of the sequence n times
    member xs.RepeatElements(n: int) =
        seq { for x in xs do for i in 1 .. n do yield x }

First example works fine however for the second one I just get an error saying "type abbreviations cannot have members".

I am currently using .Net 4.5.1 and F# 3.1

Upvotes: 2

Views: 1204

Answers (1)

latkin
latkin

Reputation: 16792

Type extensions can be thought of more or less like extensions members. You are not creating a new type, you are just declaring methods, properties, etc which the language allows you to consume with a syntax that looks like they were part of an existing type.

A true override can only be done when you have created a new class inheriting from the guy whose members you wish to override.

Unfortunately, the F# collection types are either sealed or nonpublic (or both), so you can't do this. It would probably not work out well, anyway, since these types are hardwired all over the compiler/runtime.

type myList<'t>() =
    inherit list<'t>() // error FS0945: Cannot inherit a sealed type
    override this.ToString() = "woooo"

You can work around in various ways, but it's not quite seamless. Here's a basic approach that works pretty well

module CustomStr =
    type ToStringWrapper(toString) =
        override this.ToString() = toString ()

    let list lst = ToStringWrapper(fun _ -> lst |> List.map (sprintf "[%O]") |> String.concat "")
    let seq s = ToStringWrapper(fun _ -> s |> Seq.map (sprintf "{%O}") |> String.concat "")



{1..3} |> CustomStr.seq |> printfn "%A"
[1;2;3] |> CustomStr.list |> printfn "%A"

// {1}{2}{3}
// [1][2][3]

Upvotes: 6

Related Questions