【问题标题】:F# Code is not sufficiently generic (using a static member constraint)F# 代码不够通用(使用静态成员约束)
【发布时间】:2019-06-10 19:30:57
【问题描述】:

我正在尝试创建一个通用函数来检查记录是否采用有效格式,假设记录实现了静态成员有效。当尝试在 Bolero (Blazor) 框架内的 ElmishComponent 中使用它时,我收到以下错误

此代码不够通用。 ^childModel : (static member valid : ^childModel -> bool) 时的类型变量 ^childModel 无法泛化,因为它会超出其范围

使用以下代码

module Modal =
    type Message<'childModel, 'childMessage> = | Confirm of 'childModel | Cancel | ChildMessage of 'childMessage
    type Model<'T> = { Display : bool; Title : string; Child : 'T }
    let inline valid (x: ^t) =
        (^t: (static member valid: ^t -> bool) (x))

    type Component<'T, ^childModel, 'childMessage when 'T :> ElmishComponent< ^childModel, 'childMessage> and ^childModel : (static member valid: ^childModel -> bool)>() =
        inherit ElmishComponent<Model<'childModel>, Message<'childModel, 'childMessage>>()

        // Error is highlighted on this line
        override this.View model dispatch = 
            cond model.Display <| function
            | true ->
                div [ attr.style (if model.Display then "background: lightblue;" else "background: grey;") ] [
                    h3 [] [ text model.Title ]
                    ecomp<'T,_,_> model.Child (dispatch << ChildMessage)
                    p [] []
                    button [ 
                        // This is where I use the valid function
                        attr.disabled (if valid model.Child then null else "true")
                        on.click (fun _ -> dispatch <| Confirm model.Child)
                    ] [ text "Confirm" ]
                    button [ on.click (fun _ -> dispatch Cancel) ] [ text "Cancel" ]
                ]
            | false ->
                empty

【问题讨论】:

    标签: .net f# blazor bolero


    【解决方案1】:

    我可能遗漏了一些东西,但在我看来,更简单的方法是使用子模型实现的接口 - 然后您根本不必担心静态成员约束:

    type IValidable =
      abstract IsValid : bool
    
    type Component<'T, 'childModel, 'childMessage when 
          'T :> ElmishComponent< 'childModel, 'childMessage> and 
          'childModel :> IValidable>() =
        inherit ElmishComponent<Model<'childModel>, Message<'childModel, 'childMessage>>()
        override this.View model dispatch = 
            let test = model.Child.IsValid            
            ()
    

    【讨论】:

    • 正确,这就是我最终的结果。 AFAIK 虽然我无法在现有类型(例如:第三方组件)上实现 IValidable 接口,但我可以使用静态方法来实现。虽然我想我总是可以创建一个继承自 3rd 方组件的新类型并在其上实现接口
    • 作为一些额外的上下文,我试图模拟像这篇文章这样的类型类:withouttheloop.com/articles/…
    猜你喜欢
    • 1970-01-01
    • 2020-12-20
    • 1970-01-01
    • 2022-01-22
    • 2011-01-24
    • 2018-02-26
    • 1970-01-01
    • 2011-06-07
    • 1970-01-01
    相关资源
    最近更新 更多