F # general encryption restriction error message

Just for fun, I played with type emulation in F # using the ideas presented here here . I created a class of the following type to represent values ​​that have a "successor", for example. next 1 = 2, next today = tomorrow, etc .:

type Next = Next with static member (++) (Next, x:int) = x + 1 static member (++) (Next, x:DateTime) = x.AddDays 1.0 let inline next x = Next ++ x let v1 = next 1 // v1 = 2 let v2 = next DateTime.Now // v2 = Now + 1 day 

Now I want to use the "nextable" types in the generic class:

 type UsesNextable<'T>(nextable: 'T) = // Compile error 1 member inline this.Next = let v = next nextable // Compile error 2 v.ToString() 

But I get the following errors:

  • The signature and implementation are incompatible, since the type parameter in the class / signature has a different compilation time requirement for the element in the member / implementation
  • The signature and implementation are incompatible because declaring a parameter of type "T" requires a form constraint (Next or ^ T): (static member (++): Next * ^ T β†’ ^? 155882)

I'm more interested in what the second mistake is trying to say. What does crypto mean? 155882 I suppose this may have something to do with the fact that you cannot resolve this type. Also, assuming that he is trying to define a constraint:

 (Next or ^T) : (static member ( ++ ) : Next * ^T -> ^T) 

Is it even possible to specify a condition "or" with when 'T:... ? I cannot determine the valid syntax.

Finally, ^ T offers a parameter to a statically permitted type , but the documentation says that they cannot be used for types. Despite this, I tried to change "T to ^ T", but still got the same errors.

I understand that this example abuses the type system, so I do not suggest that the compiler can handle it. However, for my own interests, I would like to know what the error messages really mean!

0
f #
Feb 27 '15 at 9:56
source share
1 answer

The problem is that .NET does not support static constraints. F # allows them to embed functions that are compiled into static methods, but cannot encode it into the standard .NET type. In your code, the generic type you want to create will have a type parameter with a static constraint that .NET cannot represent.

You can change your method to static and it will work fine:

 type UsesNextable() = static member inline Next(nextable) = let v = next nextable v.ToString() 

Your type can still be generic if you want, but you should avoid referencing the type parameter with a static constraint, for example, this will work:

 type UsesNextable<'T>() = static member inline NextOf(n:'U) = let v = next n in v.ToString() 

But not this:

 type UsesNextable<'T>() = static member inline NextOf(n:'T) = let v = next n in v.ToString() 

Solving the first problem, you will see that both error messages disappear because the second is connected to the first, where the type system cannot encode the restriction, but now it can figure it out. ^?155882 represents a static constraint type variable that the type system could not infer.

Please note that changing from 'T to Λ†T does not change anything, in fact both refer to the same type variable, the only thing you have to use a hat when calling the method.

Finally, about what you cannot write:

 let inline next v = ((Next or ^T) : (static member ( ++ ) : Next * ^T -> ^T) Next, v) 

which is clearly a mistake, because F # can output it, but you cannot write it, which is incompatible. I already reported this a while ago, and they told me that they would fix it in the future.

There are many ways to get around this restriction by forcing F # to infer a type instead of writing it directly; here is one solution for the ruler:

 let inline next v = ((^Next or ^T) : (static member ( ++ ) : ^Next * ^T -> ^T) Next, v) 

It will generate a warning, but you can disable it with the nowarn directive or by adding a parameter to a function containing an instance of type Next .

+5
Feb 27 '15 at 11:14
source share



All Articles