Question

In F# Interactive (fsi), you can use AddPrinter or AddPrinterTransformer to provide pretty printing for a type in the interactive session. How can I add such a printer for a generic type? Using the wildcard _ for the type doesn't work:

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

The printer just isn't used.

Putting in a type parameter also gives a warning:

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

which is not what I want, either.

Était-ce utile?

La solution

This won't work for the general case, but since it appears you're working with your own type (at least in your example), and assuming you don't want to affect ToString, you could do something like this:

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)

Output:

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

For a third-party generic type you could use AddPrintTransformer and reflection to get the value to be displayed. An interface is just easier if you have the source.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top