F# Interactive - how to make it print properties of an object, when the latter is enumerable
f#, f#-interactive
Solution
You can provide a custom printer using `fsi.AddPrinter`. It takes a function that specifies how to format a specific type - I don't think there is an easy way to do this generically, but you can use non-generic `IEnumerable` in this case. The following prints the sequence using the default printing and adds `Count`:
fsi.AddPrinter(fun (en:System.Collections.IEnumerable) ->
let count = Seq.cast<obj> en |> Seq.length
sprintf "%A { Count = %d }" en count
)
For example:
> l;;
val it : List<int> = seq [] { Count = 0 }
> seq { 1 .. 100000 };;
val it : seq<int> = seq [1; 2; 3; 4; ...] { Count = 100000 }
Funnily enough, this also changes printing for strings, but you could avoid that by adding the custom properties only when `en` value is not of type string.
> "hello";;
val it : string = "hello" { Count = 5 }
Problem
It's easier to show on example. If I send the following to F# interactive ``` type Person = {Name : string; Age : int} let joe = {Name = "Joe"; Age=30} ``` The output is: ``` type Person = {Name: string; Age: int;} val joe : Person = {Name = "Joe"; Age = 30;} ``` Fsi is smart enough to print all the properties. Sending the following, line-by-line ``` let l = new List<int>() l ``` results in ``` val l : List<int> val it : List<int> = seq [] ``` Fsi sees that `l` implements `IEnumerable`, and (rightfully) thinks this is what I expect to see. But there are other properties in `l`, notably `Count` and `Capacity`. (That's not that important for lists, but it is for complex types in my case) How do I make F# interactive print out the properties of an object and ignore it being `IEnumerable`? (just like for the type `Person` in the first example)