I have the following error:
Library.fs(86, 40): [FS0193] Type constraint mismatch. The type 'struct (DateTime * Intervals * float * float) option list' is not compatible with type 'Collections.Generic.List<struct (DateTime * Intervals * float * float)>'
The issue is that the F# generates a struct option list and the C# is expecting an IEnumerable with the same types instead.
How can that be converted?
Edit:
here is the full error message:
Library.fs(80, 40): [FS0001] The type 'struct (DateTime * Intervals * float * float) option list' is not compatible with the type 'Collections.Generic.List'
Library.fs(80, 40): [FS0193] Type constraint mismatch. The type 'struct (DateTime * Intervals * float * float) option list' is not compatible with type 'Collections.Generic.List'
Library.fs(81, 16): [FS0001] The type ''a option' does not match the type 'unit'
If I fill the structure with fields I know are not optional, I get the same error:
struct (DateTime.MinValue, Intervals.Tick, 0.0, 0.0)
Screenshot added:
Edit:
I added the ToList() conversion, but it didn't help:
To create List<T> out of any other enumerable (including F# list) use the .ToList extension method from System.Linq.Enumerable:
open System.Linq
...
db.AddQuotesList(Candle.Intervals.Tick, output.ToList())
Another way is to use one of List's own constructors, which takes an enumerable as argument:
open System.Collections.Generic
...
db.AddQuotesList(Candle.Intervals.Tick, List(output))
Keep in mind, however, that doing this means memory allocation: List is not "lazy" like IEnumerable is, it will allocate a block of memory for all items when you construct it.
Related
TweenAnimationBuilder(
tween: Tween<int>(begin: 0, end: 1),
builder: (_, value, __) {
return Container();
},
)
I'm providing a Tween<int> to tween, and according to my understanding, the value parameter in the builder should be of type int (at runtime it is definitely of type int but not at the compile time). Why is that so?
On the contrary, in the following code:
List<T> _getNewList<T>(List<T> list) => List<T>.from(list);
This code can infer its type from the arguments supplied.
final foo = _getNewList(<int>[1, 2]); // foo is of type `List<int>`
The way Dart type inference works is that a missing type argument, like the <T> type parameter on TweenAnimationBuilder is first checked against the calling context. If that doesn't give a type, then the arguments are analyzed individually without any hint to the type variable's type, and then the type argument is inferred as something allowing the argument's types.
In this case, tween is analyzed to have type Tween<int> and builder is analyzed to have type Widget Function(BuildContext, dynamic, Widget) because there is no clue to the second argument's type from the context.
The type analysis does not use information derived from one argument to infer T before finding the type of the second argument (that could be wrong if case the second one requires a looser type).
Then the type inference tries to find a type argument to TweenAnimationBuilder satisfying both of these, which ends up with <dynamic> because of the builder type.
If you only have one argument, or only one argument depending on the type argument, or you have multiple arguments that agree on the type, then things work out.
If you have multiple parameters depending on the type variable, no context type which locks the type variable down, and only one of the arguments actually constrain the type argument, then ... well, this happens, the other argument is unconstrained and that makes the inferred type argument be dynamic. Either write TweenAnimationBuilder<int>(...) or ..., builder: (_, int value, _) => ... so that you have a type hint on all paths.
For the Froto project (Google Protobuf in F#), I am trying to update the deserialization code from using 'a ref objects to passing values byref<'a>, for performance.
However, the code below fails on the hydrator &element field line:
type Field = TypeA | TypeB | Etc
let hydrateRepeated
(hydrator:byref<'a> -> Field -> unit)
(result:byref<'a list>)
(field:Field) =
let mutable element = Unchecked.defaultof<'a>
hydrator &element field
result <- element :: result
error FS0421: The address of the variable 'element' cannot be used at this point
Is there anything I can do to get this code to work without changing the signature of the hydrator parameter?
I'm very aware that I could use hydrator:'a ref -> Field -> unit and get things to work. However, the goal is to support deserializing into record types without needing to create a bunch of ref objects on the heap every time a record is deserialize.
Note that the following code is perfectly legal and has the same signature as the hydrator function declaration, above, so I'm unclear on what the problem is.
let assign (result:byref<'a>) (x:'a) =
result <- x
let thisWorks() =
let mutable v = Unchecked.defaultof<int>
assign &v 5
printfn "%A" v
I'll try to clarify what I was saying in my comments. You're right that your definition of assign is perfectly fine, and it appears to have the signature byref<'a> -> 'a -> unit. However, if you look at the resulting assembly, you'll find that the way it's compiled at the .NET representation level is:
Void assign[a](a ByRef, a)
(that is, it's a method that takes two arguments and doesn't return anything, not a function value that takes one argument and returns a function that takes the next argument and returns a value of type unit - the compiler uses some additional metadata to determine how the method was actually declared).
The same is true of function definitions that don't involve byref. For instance, assume you've got the following definition:
let someFunc (x:int) (y:string) = ()
Then the compiler actually creates a method with the signature
Void someFunc(Int32, System.String)
The compiler is smart enough to do the right thing when you try to use a function like someFunc as a first class value - if you use it in a context where it isn't applied to any arguments, the compiler will generate a subtype of int -> string -> unit (which is FSharpFunc<int, FSharpFunc<string, unit>> at the .NET representation level), and everything works seamlessly.
However, if you try to do the same thing with assign, it won't work (or shouldn't work, but there are several compiler bugs that may make it seem like certain variations work when really they don't - you might not get a compiler error but you may get an output assembly that is malformed instead) - it's not legal for .NET type instantiations to use byref types as generic type arguments, so FSharpFunc<int byref, FSharpFunc<int, unit>> is not a valid .NET type. The fundamental way that F# represents function values just doesn't work when there are byref arguments.
So the workaround is to create your own type with a method taking a byref argument and then create subtypes/instances that have the behavior you want, sort of like doing manually what the compiler does automatically in the non-byref case. You could do this with a named type
type MyByrefFunc2<'a,'b> =
abstract Invoke : 'a byref * 'b -> unit
let assign = {
new MyByrefFunc2<_,_> with
member this.Invoke(result, x) =
result <- x }
or with a delegate type
type MyByrefDelegate2<'a,'b> = delegate of 'a byref * 'b -> unit
let assign = MyByrefDelegate2(fun result x -> result <- x)
Note that when calling methods like Invoke on the delegate or nominal type, no actual tuple is created, so you shouldn't be concerned about any extra overhead there (it's a .NET method that takes two arguments and is treated as such by the compiler). There is the cost of a virtual method call or delegate call, but in most cases similar costs exist when using function values in a first class way too. And in general, if you're worried about performance then you should set a target and measure against it rather than trying to optimize prematurely.
Leaving aside whether we should use units of measure for unitless concepts like angles, suppose I have define degree and radian units in F#
type [<Measure>] degree =
static member ToRadians (d:float<degree>) : float<radian> = d * (Math.PI * 1.<radian>) / 180.0<degree>
and [<Measure>] radian =
static member ToDegrees (r:float<radian>) : float<degree> = r * 180.0<degree> / (Math.PI * 1.<radian>)
I can use them relatively easily like
4.0<degree> |> degree.ToRadians
It seems like extension members would be even handier. So I could just say
let d = 4.0<degree>
let r = d.ToRadians()
But I can't define the extension member the obvious way
type float<degree> with
member degrees.ToRadians() = degree.ToRadians(degrees)
... this gets me the following error
error FS0010: Unexpected identifier in type name. Expected infix operator, quote symbol or other token.
Is there a syntactic trick for extension members on units of measure in F#, or is the feature supported?
F# extension members are different from C# extension members in that you can't define extensions of constructed generic types. For instance, you can define extensions on seq<'t>, but not seq<int>. In other words, extension members really act like members of the type, rather than static methods. This applies to measure types too, so you can't define an extension on float<degree>, but you can define an extension on float<[<Measure>]'u>:
type float<[<Measure>]'u> with
member f.Squared() = f * f
[<Measure>]
type m
let area = 2.0<m>.Squared()
However, I don't see how this helps you in your case...
if I want to define a extension method for float array like standard deviation, would it be better to use module extension on Array module or extension on type float[]?
like :
module Array =
let std (arr: float[]) = ...
or
type float ``[]`` with
member this.std = ...
If I do type extension as the latter, would the std be only calculated once or every time it is used?
And, what is the right format for the latter, apprently type float ``[]`` with does not comile... thanks.
In this case, you can't define a type extension so the issue is moot - you must use an extension of the Array module. The reason that you can't define a type extension is that in F#, type extensions must exactly mirror type definitions, so you can define a type extension on the generic 'a list type, for instance, but not on the constructed type string list. Similarly, you could define an extension method on the (simulated) generic array type
'a ``[]``
but not on the constructed array type
float ``[]``
This behavior is different than C#, where it is possible to write extension methods on constructed generic types.
In F# what is the type annotation for a typed list (e..g list of int)? With a simple function I can do annotations as follows:
let square(x:int) = ...
I've annotated x as an int type. But what if I want to do a type annotation for an int list? For example, let's say I have a max function that expects a list - how would I do a type annotation for it?
let max(numbers:??) = ...
There are two options:
let max (numbers:int list) = ...
let max (numbers:list<int>) = ...
The first version uses syntax that is inherited from OCaml (and is frequently used for primitive F# types such as lists). The second version uses .NET syntax (and is more frequently used for .NET types or when writing object-oriented code in F#). However, both of them mean exactly the same thing.
In any case, the form of type annotation is always (<something> : <type>) where <something> is either a pattern (as in parameter list) or an expression. This means that int list and list<int> are just names of types. F# Interactive prints the type if you enter some value, so you can use this to learn more about how type names are written:
> [1;2;3]
val it : int list = [ 1; 2; 3 ]