类型定义中的Seq约束

Gho*_*ack 4 f# seq

此类型定义有效:

type Model<'t,'u when 't :> seq<'u> >(query: unit -> 't) = class end
Run Code Online (Sandbox Code Playgroud)

但是,对我来说,'u这里是多余的,但下一个定义是:

type Model<'t when 't :> seq<_> >(query: unit -> 't) = class end
Run Code Online (Sandbox Code Playgroud)

产生错误:

此声明中不允许使用匿名类型变量- F# Compiler (715)

紧凑

最紧凑的形式:

type Model<'t>(query:unit -> #seq<'t>) = class end
Run Code Online (Sandbox Code Playgroud)

在实例创建过程中:

Query.users |> Model
Run Code Online (Sandbox Code Playgroud)

产生错误:

类型约束不匹配。类型unit -> (string * int) list
与类型不兼容unit -> 'a
F# Compiler (193)

可能是由于此处所述,为什么记录类型定义中不允许使用灵活类型?。但是无论如何,错误说明对我来说还是不清楚的,用(string * int) list代替代替有'a什么问题?

背景

实类型Model是数据库查询的包装,它实现INotifyPropertyChanged并包含mutabletype的状态Outcome

type 't Outcome =
    | Empty
    | Loading
    | Success of 't
    | Fault   of string * string
Run Code Online (Sandbox Code Playgroud)

#seq<'t>需要类型约束检测Empty用的情况下Seq.isEmpty在通用的方式,由于查询可返回seqlistarray

Tom*_*cek 5

正如@kvb所解释的那样,问题在于您不能具有泛型构造函数-因此您可以在整个类中引入新的类型参数(如您在第一个示例中所做的那样),或者返回类型query必须为seq<'t>(因为编译器会迫使您在其他示例中执行此操作)。

如果要将事情封装在一个类中,一个不错的技巧是使构造函数私有并添加一个静态Create方法,该方法可以具有所需的额外泛型参数:

type Model<'t> private(query:unit -> seq<'t>) = 
  static member Create(query:unit -> #seq<'t>) =
    Model(fun () -> query () :> _)
Run Code Online (Sandbox Code Playgroud)