fsprojects / IfSharp

F# for Jupyter Notebooks
Other
440 stars 71 forks source link

Util.Table broken for anonymous records #233

Open rudihorn opened 5 years ago

rudihorn commented 5 years ago

Description

This seems to more be an F# bug related to a unification error with F# anonymous record types (possibly a dotnet restriction?).

Repro steps

[ {|id=5; name = "hello"|} ] |> Util.Table

Expected behavior

Table output

Actual behavior

Error message:

Type constraint mismatch. The type '{|id : int ; name : string|} list'
is not compatible with type 'seq<{|id : int ; name : string|}>'

Known workarounds

Define it within a module:

open System

module MUtil =
    let Row (columns:seq<Reflection.PropertyInfo>) (item:'A) =
        columns
        |> Seq.map (fun p -> p.GetValue(item))
        |> Seq.map Convert.ToString
        |> Seq.toArray

    let Table (items:seq<'A>, propertyNames:seq<string> option) =
        let properties = 
            if propertyNames.IsSome then
                typeof<'A>.GetProperties()
                |> Seq.filter (fun x -> (propertyNames.Value |> Seq.exists (fun y -> x.Name = y)))
                |> Seq.toArray
            else
                typeof<'A>.GetProperties()
        { 
            Columns = properties |> Array.map (fun x -> x.Name);
            Rows = 
                items 
                |> Seq.map (Test.MyRow properties)
                |> Seq.toArray
        }

    let DefaultTable items = Table (items, None)

Then call:

[ {|id=5; name = "hello"|} ] |>  MUtil.DefaultTable

Related information

rudihorn commented 5 years ago

Questions I still have:

cgravill commented 5 years ago

It's not a .NET Core issue.

I'd be tempted to just initialise as a seq or convert to that:

[ {|id=5; name = "hello"|} ] |> Seq.ofList |> Util.Table

but improving compatibility seems like a good idea too.

cgravill commented 5 years ago

To confirm the implicit conversion works for explict records:

image

https://github.com/fsprojects/IfSharp/blob/5a415a7618ce91c41ba441688db29fbaa8d03410/src/IfSharp.Kernel/Util.fs#L86-L100

rudihorn commented 5 years ago

To confirm the implicit conversion works for explict records:

image

https://github.com/fsprojects/IfSharp/blob/5a415a7618ce91c41ba441688db29fbaa8d03410/src/IfSharp.Kernel/Util.fs#L86-L100

Yes this is what was confusing me about this. The conversion to a seq first works for me though.