Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

f#

fsi

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.

like image 450
Jeffrey Sax Avatar asked Feb 21 '13 21:02

Jeffrey Sax


1 Answers

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.

like image 176
Daniel Avatar answered Nov 08 '22 14:11

Daniel