F# -> Generic type - Multiple not struct - f#

My first thought was:
type ManyNavigationPropertyInfo<'a,'b>(cfg:ManyNavigationPropertyConfiguration<'a, 'b>) =
however it resolves 'a and 'b as obj, but it should be classes - therefore I did:
type ManyNavigationPropertyInfo<'a
when 'a : not struct,'b when 'b : not
struct>(cfg:ManyNavigationPropertyConfiguration<'a,
'b>) =
but that just throws an error saying
Unexpected symbol ',' in type name.
Expected '>' or other token.
What's the correct way for declaring such a type?
UPDATE:
My full code is:
type ManyNavigationPropertyInfo<'a,'b>(cfg:ManyNavigationPropertyConfiguration<'a, 'b>) =
member x.WithMany (expr: Expr<'a -> ICollection<'b>>) =
cfg.WithMany(ToLinq(expr))
and it comes up with 2 compiler errors saying that 'a and 'b should be not struct.

Your first thought is correct. You should be able to just write:
type ManyNavigationPropertyInfo<'a,'b>
(cfg:ManyNavigationPropertyConfiguration<'a, 'b>) =
// ...
The problem is probably somewhere later in the body of the type. From something that you wrote in the body, the compiler thinks that 'a and 'b must be of type obj (e.g. you're passing values of this type somewhere where obj is expected, or probably something more subtle).
You can try adding type annotations in the body of the class - this usually helps to find the issue, because the error message changes when you annotate the bit that F# compiler interprets differently than you expected.
To solve the immediate problem in your question - the syntax for specifying constraint is a bit different (first write all type variables and then constraints):
type ManyNavigationPropertyInfo<'a, 'b when 'a : not struct and 'b : not struct>( ... )
(But if you can post larger portion of code, maybe somebody can give a concrete advice.)

Related

"Invalid constraint: the type used for the constraint is sealed" is invalid

I'm wish to use F#'s type inference to infer the types of my code simply by the methods/functions that are called.
This CAN be achieved quite nicely by using extension methods of the form...
[<Extension>]
type AttributeExtensions =
[<Extension>]
static member ``BroadcastOffset``<'a, 'b when 'a :> ``BroadcastOffset``<'b>> (this: 'a) =
this.``
when I have code that reads
x.BroadcastOffset()
type inference will kick in and infers that x, must indeed be of type BroadcastOffset<'a>.
A small fly in the ointment though is F#'s own types for example, if I write
x.Value
F# will not infer its an Option<_>, thats understandable, but I can use the same extension trick to get there?
[<Extension>]
type AttributeExtensions =
[<Extension>]
static member Value<'a,'b when 'a :> Option<'b>> (this: 'a) =
this.Value
and that SHOULD in theory mean
x.Value()
should trigger the inference of x being an Option<_>
sadly this ISNT the case, because F# rejects the extension method as an invalid constraint because Option<_> is sealed and thus 'a can only have 1 solution.
True 'a CAN only have 1 solution but, in my book that does NOT make the constraint invalid, it is perfectly valid, just trivial to infer, and because of this overzelous rejection, I am frustrated in making "Value" trigger type inference.
any ideas how to get around it? (apart from changing the F# compiler myself).
(I can of course define a function 'Value' instead, but my intention is to use F# to infer types from "methods", and extension methods fit the requirement where simple functions don't...I have my reasons)
I got compile errors using your code and then factored out what I think you are after into a function, then used the function in the extension. This allowed me to call .Value() and it work out that it was of type 'a option which is what I think you were after?
open System.Runtime.CompilerServices
let v (x : 'a option) = x.Value
[<Extension>]
type AttributeExtensions =
[<Extension>]
static member Value(this) = v(this)
let myFunc o = o.Value()

The parameter has been used in a way that constrains it to always be DerrivedType

Hi I just started programming in F# and am stuck on a type issue.
I have this function:
member private this.UpdateStats<'T when 'T :> StatisticsBase>(passed: bool, stats: 'T) =
//more stuff..
stats
I'm calling it like this:
this.UpdateStats<GroupStats>(true, GroupStats(Id = Guid.NewGuid()))
The compiler says:
The parameter has been used in a way that constrains it to always be GroupStats.
GroupStats inherit from StatisticsBase. What do I have to do to make the function usable for all entities that inherit from StatisticsBase?
types:
[<AllowNullLiteral>]
type StatisticsBase() =
member val Id = String.Empty with get,set
[<AllowNullLiteral>]
type GroupStats() =
inherit Stats()
StatisticsBase actually inherits from a C# type and is used in a repository, but I can reproduce the error with the code above
After much back and forth, we have been able to ascertain that your actual non-working code is like this (tip for the future: provide more information):
type SomeType() =
member this.M2() =
this.M<GroupStats>(true, GroupStats())
member private this.M<'T when 'T :> Stats>(x: bool, t: 'T) =
t
This code will indeed produce the described error. This is because F# type inference works top-to-bottom, left-to-right. But there is an exception: classes (and other mutually recusrive definition groups) get two passes of type inference - first signatures, then bodies.
When the compiler first comes across the body of M2, it determines that method M must return GroupStats. Later, when the compiler comes across the body of M, it sees that M's return value is the same as parameter t, which means that M must return 'T. But since the compiler already knows, from examining the body of M2, that M must return GroupStats, it follows that 'T must be GroupStats.
This doesn't happen if M is defined before M2: in this case, type inference will first encounter the body of M and correctly determine its return type to be 'T, which will then match up with the body of M2, and the will be no problem.
From the above, two solutions can be formulated: first, you could define M before M2. Second, you could just explicitly specify the return type of M:
member private this.M<'T when 'T :> Stats>(x: bool, t: 'T): 'T =
t
This way, its return type will become known after the first pass, and the problem disappears.

Order of type constraints in F#

This works in F#4.0:
type Something<'a, 'b when 'b :> seq<'b>>() =
This doesn't:
type Something<'b when 'b :> seq<'b>, 'a>() =
Unexpected symbol ',' in type name. Expected '>' or other token.
What's the reason that the order of the type constraint matter?
Because it is in the spec - the relevant part is this (from the start of section 5):
typar-defns:= < typar-defn, ..., typar-defn typar-constraints_opt>
the constraints need to go at the end.
In this typar-constraints must always start with when and can't appear anywhere else.
Type constraints and type arguments are two different things. In your example, 'a and 'b are two type arguments, and when 'b :> seq<'b> is the (only) constraint.
Now, the way you've written your first example it seems to suggest that the type argument definitions have something to do with the type constraints, but that's only in the appearance. Note this (working) code:
type Something<'b, 'a when 'b :> seq<'b>>() =
member this.A (a : 'a, b : 'b) =
()
First, you define all the type arguments. Only afterwards come the type constraints, and the constraint still applies to 'b, not 'a - while it looks a bit confusing, the constraint expression isn't 'a when 'b :> seq<'b>, it's just the when 'b :> seq<'b>.
This is actually pretty much the same as in C#, another .NET language:
public class Something<TA, TB> where TA: someConstraint where TB: someOtherConstraint
The constraints are more visually separate in C#, so people don't tend to make the mistake you made in F#.
Along with the above answers, the ordering allows the constraints to depend on multiple types. e.g.
type Something<'a, 'b when 'b :> seq<'a>>() =
Note:seq<'a> not seq<'b>

Delegate/Func conversion and misleading compiler error message

I thought that conversions between F# functions and System.Func had to be done manually, but there appears to be a case where the compiler (sometimes) does it for you. And when it goes wrong the error message isn't accurate:
module Foo =
let dict = new System.Collections.Generic.Dictionary<string, System.Func<obj,obj>>()
let f (x:obj) = x
do
// Question 1: why does this compile without explicit type conversion?
dict.["foo"] <- fun (x:obj) -> x
// Question 2: given that the above line compiles, why does this fail?
dict.["bar"] <- f
The last line fails to compile, and the error is:
This expression was expected to have type
System.Func<obj,obj>
but here has type
'a -> obj
Clearly the function f doesn't have a signature of 'a > obj. If the F# 3.1 compiler is happy with the first dictionary assignment, then why not the second?
The part of the spec that should explain this is 8.13.7 Type Directed Conversions at Member Invocations. In short, when invoking a member, an automatic conversion from an F# function to a delegate will be applied. Unfortunately, the spec is a bit unclear; from the wording it seems that this conversion might apply to any function expression, but in practice it only appears to apply to anonymous function expressions.
The spec is also a bit out of date; in F# 3.0 type directed conversions also enable a conversion to a System.Linq.Expressions.Expression<SomeDelegateType>.
EDIT
In looking at some past correspondence with the F# team, I think I've tracked down how a conversion could get applied to a non-syntactic function expression. I'll include it here for completeness, but it's a bit of a strange corner case, so for most purposes you should probably consider the rule to be that only syntactic functions will have the type directed conversion applied.
The exception is that overload resolution can result in converting an arbitrary expression of function type; this is partly explained by section 14.4 Method Application Resolution, although it's pretty dense and still not entirely clear. Basically, the argument expressions are only elaborated when there are multiple overloads; when there's just a single candidate method, the argument types are asserted against the unelaborated arguments (note: it's not obvious that this should actually matter in terms of whether the conversion is applicable, but it does matter empirically). Here's an example demonstrating this exception:
type T =
static member M(i:int) = "first overload"
static member M(f:System.Func<int,int>) = "second overload"
let f i = i + 1
T.M f |> printfn "%s"
EDIT: This answer explains only the mysterious promotion to 'a -> obj. #kvb points out that replacing obj with int in OPs example still doesn't work, so that promotion is in itself insufficient explanation for the observed behaviour.
To increase flexibility, the F# type elaborator may under certain conditions promote a named function from f : SomeType -> OtherType to f<'a where 'a :> SomeType> : 'a -> OtherType. This is to reduce the need for upcasts. (See spec. 14.4.2.)
Question 2 first:
dict["bar"] <- f (* Why does this fail? *)
Because f is a "named function", its type is promoted from f : obj -> obj following sec. 14.4.2 to the seemingly less restrictive f<'a where 'a :> obj> : 'a -> obj. But this type is incompatible with System.Func<obj, obj>.
Question 1:
dict["foo"] <- fun (x:obj) -> x (* Why doesn't this, then? *)
This is fine because the anonymous function is not named, and so sec. 14.4.2 does not apply. The type is never promoted from obj -> obj and so fits.
We can observe the interpreter exhibit behaviour following 14.4.2:
> let f = id : obj -> obj
val f : (obj -> obj) (* Ok, f has type obj -> obj *)
> f
val it : ('a -> obj) = <fun:it#135-31> (* f promoted when used. *)
(The interpreter doesn't output constraints to obj.)

Are Infinite Types (aka Recursive Types) not possible in F#?

I was chatting with Sadek Drobi on twitter when be brought up that F# didn't seem to support Infinite Types. It turns out that in C# you can do something along these lines:
delegate RecDelegate<T> RecDelegate<T>(T x);
However, after some experimentation on both our parts, we determined that the same in F# seems impossible both implicit and explicitly.
Explicit:
type 'a specialF = 'a->specialF<'a>
error FS0191: This type definition
involves an immediate cyclic reference
through an abbreviation, struct field
or inheritance relation.
Implicit:
let rec specialF (x: 'a) = specialF
Type mismatch. Expecting a 'b but
given a 'a -> 'b. The resulting type
would be infinite when unifying ''b'
and ''a -> 'b'.
Of course, these are intentionally simple samples.
I was wondering if I am somehow mistaken. Perhaps I missed some type of necessary annotation?
You can also do something like
type 'a RecType = RecType of ('a -> 'a RecType)
to create a named type through which to perform the recursion. Now this works:
let rec specialF = RecType (fun _ -> specialF)
type d<'T> = delegate of 'T -> d<'T> //'
let del : d<int> = null
let anotherDel = del.Invoke(1).Invoke(2).Invoke(3)
I think you need a named type that is representable directly in CLI to break the recursion, so in F# this means you need an actual delegate type as well.
Recursive record types should work as well.
type A = { A : A }
let rec a : A = { A = a }
I'd be interested in a practical application. Or even an impractical one :)

Resources