Skip to content

Util.Table broken for anonymous records #233

Open

Description

@rudihorn

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

  • Operating system: Ubuntu
  • Branch: Master
  • CoreCLR

Activity

  1. rudihorn commented on Jun 28, 2019

    @rudihorn
    ContributorAuthor

    Questions I still have:

    • Is this a dotnet core issue?
    • Is this issue known and tracked?
    • Is it worth trying to issue a workaround and switch to an F# module in IfSharp
  2. cgravill commented on Jun 28, 2019

    @cgravill
    Member

    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.

  3. cgravill commented on Jun 28, 2019

    @cgravill
    Member

    To confirm the implicit conversion works for explict records:

    image

    static member Table (items:seq<'A>, ?propertyNames:seq<string>) =
    // get the properties
    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 (Util.Row properties) |> Seq.toArray;
    }

  4. rudihorn commented on Jun 28, 2019

    @rudihorn
    ContributorAuthor

    To confirm the implicit conversion works for explict records:

    image

    static member Table (items:seq<'A>, ?propertyNames:seq<string>) =
    // get the properties
    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 (Util.Row properties) |> Seq.toArray;
    }

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions