This type definition works:
type Model<'t,'u when 't :> seq<'u> >(query: unit -> 't) = class end
However, as for me the 'u
is redundant here, but next definition:
type Model<'t when 't :> seq<_> >(query: unit -> 't) = class end
produces the error:
Anonymous type variables are not permitted in this declaration -
F# Compiler (715)
The most compact form:
type Model<'t>(query:unit -> #seq<'t>) = class end
during instance creation:
Query.users |> Model
produces error:
Type constraint mismatch. The type
unit -> (string * int) list
is not compatible with typeunit -> 'a
F# Compiler (193)
Probably, because of described here Why are flexible types not allowed in record type definitions?. But anyway the error description is unclear for me, what is wrong in substituting (string * int) list
instead of 'a
?
The real type Model
is a wrapper for a database query, it implements INotifyPropertyChanged
and contains mutable
state of type Outcome
:
type 't Outcome =
| Empty
| Loading
| Success of 't
| Fault of string * string
The #seq<'t>
type constraint is needed to detect Empty
case with Seq.isEmpty
in generic way due to a query can return seq
or list
or array
As explained by @kvb, the problem is that you cannot have generic constructors - so you can either introduce a new type parameter to the entire class (as you did in your first example), or the return type of query
will need to be just seq<'t>
(as the compiler forces you to do in your other examples).
If you want to keep things encapsulated in a class, one nice trick is to make the constructor private and add a static Create
method which can have the extra generic parameter that you need:
type Model<'t> private(query:unit -> seq<'t>) =
static member Create(query:unit -> #seq<'t>) =
Model(fun () -> query () :> _)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With