How do I add a pretty printer for a generic type to fsi?

f#, fsi

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.

Problem

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.

Original source