如何覆盖内置集合中的tostring

Mic*_*ahl 2 f#

如何覆盖内置集合(如map或sequence)中的tostring函数,以便printfn将使用这个新的自定义tostring函数?

我猜它应该是这样的

type seq<'T> with
    override xs.Tostring() =
        "blabla"
Run Code Online (Sandbox Code Playgroud)

然而,这只是给出错误"类型缩写不能有增加".

然后我看了msdn,发现以下关于类型扩展http://msdn.microsoft.com/en-us/library/dd233211.aspx

它声明我应该能够扩展例如int32和序列如下

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 }
Run Code Online (Sandbox Code Playgroud)

第一个例子很好但是对于第二个例子我只是得到一个错误,说"类型缩写不能有成员".

我目前正在使用.Net 4.5.1和F#3.1

lat*_*kin 6

类型扩展可以被认为或多或少像扩展成员.您没有创建类型,您只是声明语言允许您使用的方法,属性等,其语法看起来像是现有类型的一部分.

只有在创建了一个继承自要覆盖其成员的人的新类时,才能执行真正的覆盖.

不幸的是,F#集合类型是密封的或非公共的(或两者兼有),所以你不能这样做.无论如何,它可能不会很好,因为这些类型在整个编译器/运行时都是硬连线的.

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

你可以通过各种方式解决问题,但它并不是完全无缝的.这是一个非常有效的基本方法

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]
Run Code Online (Sandbox Code Playgroud)