2015-01-08 2 views
2

Как переопределить функцию tostring для встроенной коллекции, такой как карта или последовательность, так что printfn будет использовать эту новую пользовательскую функцию tostring?Как переопределить 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

+0

Это не может быть сделано вообще в .NET см [этот вопрос] (http://stackoverflow.com/questions/9697332/how-can-i-override -tostring-метод-для-всех-ienumarableint32). Однако вы можете переопределить 'printfn' для работы таким образом. – Gustavo

ответ

6

расширений типа можно считать более или менее как членов расширений. Вы не создаете тип , вы просто объявляете методы, свойства и т. Д., Которые язык позволяет вам использовать с синтаксисом, который выглядит как часть существующего типа.

Истинное переопределение может быть выполнено только в том случае, если вы создали новый класс, наследуемый от парня, члены которого вы хотите переопределить.

К сожалению, типы коллекции 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]