【问题标题】:how to override tostring on built in collection如何覆盖内置集合上的tostring
【发布时间】:2015-01-08 21:13:34
【问题描述】:

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

我猜应该是这样的

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

但是这只会给出错误“类型缩写不能有扩充”。

然后我查看了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 }

第一个示例运行良好,但对于第二个示例,我收到一条错误消息,提示 “类型缩写不能包含成员”。

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

【问题讨论】:

  • 在 .NET 中一般无法完成,请参阅 this question。但是,您可以重新定义 printfn 以使其工作。

标签: f#


【解决方案1】:

类型扩展可以被认为或多或少类似于扩展成员。您不是在创建 new 类型,您只是在声明方法、属性等,该语言允许您使用看起来像是 现有 的一部分的语法来使用它们输入。

只有在您创建了一个继承自您希望覆盖其成员的人的新类时,才能完成真正的覆盖。

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

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

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

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]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多