Как добавить симпатичный принтер для универсального типа в fsi?

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

> 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'.

чего я тоже не хочу

1 ответ

Решение

Это не сработает для общего случая, но, поскольку кажется, что вы работаете со своим собственным типом (по крайней мере, в вашем примере) и предполагаете, что не хотите влиять 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 и отражение, чтобы получить значение для отображения. Интерфейс становится проще, если у вас есть источник.

Другие вопросы по тегам