It's a choice we've been struggling with for a long time, because we already had the same problem in Html.Client choosing between seq<Pagelet> and seq<#Pagelet>. The problem is that in both cases upcasts are needed, just in different places.

  • If we take seq<Doc>, as is currently the case, then a cast is needed in situations such as:

    1
    2
    3
    4
    5
    6
    7
    
    let elt =
        div (
            items
            |> Seq.map (fun item ->
                // without the cast below, type error: expected Doc, got Elt
                span [text item] :> _)
        )
  • If we take seq<#Doc>, then a cast is needed in situations such as:

    1
    2
    3
    4
    5
    6
    
    let elt =
        div [
            span [text "this is an Elt"] :> Doc
            // without the cast above, type error below: expected Elt, got Doc
            text "this is a Doc"
        ]

Unfortunately there will be no catch-all solution until F# either supports type parameter covariance (which would make seq<Doc> work), or avoids freezing the type of a seq<#T> to the first element in the list/seq/array literal (which would make seq<#Doc> work). I think I'll submit a language feature proposal for the latter (the former has already been asked for a lot).

By on 8/27/2015 9:03 AM ()

Yes, I see the problem.

Here is what I'm doing to make life nice for me. It addresses this issue at the same time:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[<JavaScript>]
module Alternative =
    // these are also useful, but nothing to do with this topic
    type attr with
        static member cls = attr.``class``
        static member typ = attr.``type``

    // I use these most of the time
    let inline div atts els = divAttr atts els :> Doc
    let inline a atts els = aAttr atts els :> Doc
    let inline ul atts els = ulAttr atts els :> Doc
    let inline li atts els = liAttr atts els :> Doc

    // I use these if I need to do something imperative
    let divElt = divAttr
    let canvasElt = canvasAttr

Most of the time, I only need a Doc, so the plain HTML names like div return a Doc. On the rare occasions when I need an Elt (e.g. I need to assign to the Text field), I use divElt, which returns an Elt.

By on 8/28/2015 1:42 AM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper