2013-02-21 3 views
6

В F # Interactive (fsi) вы можете использовать AddPrinter или AddPrinterTransformer, чтобы обеспечить отличную печать для типа в интерактивном сеансе. Как добавить такой принтер для универсального типа? Используя подстановочные _ для данного типа не работает:Как добавить красивый принтер для универсального типа в fsi?

> fsi.AddPrinter(fun (A : MyList<_>) -> A.ToString());; 

Принтер просто не используется.

Ввод в параметре типа также дает предупреждение:

> fsi.AddPrinter(fun (A : MyList<'T>) -> A.ToString());; 

    fsi.AddPrinter(fun (A : MyList<'T>) -> A.ToString());; 
    -------------------------------^^ 

d:\projects\stdin(70,51): warning FS0064: This construct causes code 
to be less generic than indicated by the type annotations. The type 
variable 'T been constrained to be type 'obj'. 

, который не то, что я хочу, либо.

+2

Я уверен, что это невозможно. Тип arg требует конкретного типа. – Daniel

+0

Можете ли вы переопределить 'ToString' для' MyList <'T> '? – Daniel

ответ

7

Это не будет работать в общем случае, но поскольку оно появляется, вы работаете с вашим собственным типом (по крайней мере, в вашем примере), и если вы не хотите влиять на ToString, вы можете сделать что-то вроде это:

type ITransformable = 
    abstract member BoxedValue : obj 

type MyList<'T>(values: seq<'T>) = 
    interface ITransformable with 
    member x.BoxedValue = box values 

fsi.AddPrintTransformer(fun (x:obj) -> 
    match x with 
    | :? ITransformable as t -> t.BoxedValue 
    | _ -> null) 

Выход:

> MyList([1;2;3]) 
val it : MyList<int> = [1; 2; 3] 

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

+0

Спасибо. Но почему вы объявляете параметр AddPrintTransformer', чтобы иметь тип 'obj'? Почему бы не использовать 'ITransformable' прямо там? Или даже использовать 'AddPrinter' с функцией, которая принимает' ITransformable'? –

+0

Это 'obj', потому что я впервые пошел по пути использования отражения. Вероятно, вы можете изменить его на «ITransformable». Я думаю, что «AddPrintTransformer» лучше для того, что вы пытаетесь сделать, потому что в большинстве случаев достаточно делегировать отображаемое значение. – Daniel