This code:
let mutable x : Nullable<int64> = new Nullable<int64> 99L
let y : int64 = 88L
x <- y
produces this compile time error:
This expression was expected to have type Nullable but here has type int64
I understand the error, what I would like to know is what is the correct way (cast?) to assign the value in y (88) to x?
Use the System.Nullable constructor; for example:
>
let mutable x = System.Nullable (99L)
let y = 88L
x <- System.Nullable y;;
val mutable x : Nullable<int64> = 88L
val y : int64 = 88L
val it : unit = ()
Related
Consider a generic container like:
type Foo<'t> =
{
Foo : 't
}
This generic function works OK:
module Foo =
let inline emptyFoo () =
{
Foo = LanguagePrimitives.GenericZero
}
But this value does not:
module Foo =
let emptyFoo =
{
Foo = LanguagePrimitives.GenericZero
}
This is because the compiler infers emptyFoo to have type Foo<obj>.
However, the standard library has generic values like List.empty, so how is that achieved there?
You have to make it explicitly generic.
List.empty is implemented like this:
let empty<'T> = ([ ] : 'T list)
You could implement a List by yourself, with an empty. It looks like this.
type L<'a> =
| Null
| Cons of 'a * L<'a>
module L =
let empty = Null
let xs = Cons(1, Cons(2, L.empty))
let ys = Cons(1.0,Cons(2.0,L.empty))
So, why does L.empty in this case works in a generic way? Because the value Null has no special value attached to it. You could say, it is compatible with every other generic.
In your Record on the other hand, you always must produce a value. LanguagePrimitive.GenericZero is not some Generic value. It help so to resolve to a special zero value, and this value is determined by the other code you write.
For example
let x = LanguagePrimitives.GenericZero
is also obj
let x = LanguagePrimitives.GenericZero + 1
will be int. And
let x = LanguagePrimitives.GenericZero + 1.0
will be float. So in some case you can think of GenericZero just as a placeholder for zero for the special type you need, but the code needs to determine at this point, which type you want.
You could change your type, with an option to provide a real empty.
type Foo<'t> = {
Foo: 't option
}
module Foo =
let empty = { Foo = None }
let x = Foo.empty // Foo<'a>
let y = { x with Foo = Some 1 } // Foo<int>
let z = { x with Foo = Some 1.0 } // Foo<float>
Zero Member
Maybe you want a Zero Member on some types. For example
type Vector3 = {X:float; Y:float; Z:float} with
static member create x y z = {X=x; Y=y; Z=z}
static member (+) (a,b) = Vector3.create (a.X + b.X) (a.Y + b.Y) (a.Z + b.Z)
static member Zero = Vector3.create 0.0 0.0 0.0
static member DivideByInt(a,b) =
Vector3.create
(LanguagePrimitives.DivideByInt a.X b)
(LanguagePrimitives.DivideByInt a.Y b)
(LanguagePrimitives.DivideByInt a.Z b)
then you can write
let xs = [1;2;3]
let ys = [Vector3.create 1.0 1.0 1.0; Vector3.create 1.0 1.0 1.0]
let inline sum xs =
List.fold (fun a b -> a + b) LanguagePrimitives.GenericZero xs
let sumx = sum xs // int: 6
let sumy = sum ys // Vector3: 2.0 2.0 2.0
How can I defined the width of a random number?
let randomNumber = System.Random()
let randomBarcodePart2 = randomNumber.Next(**000000, 999999**)
I have this now, but is it possible to generate a random number, where we only defined the width.
Like this:
let randomBarcodePart2 = randomNumber.Next(6)
simple example with printf:
let t = randomNumber.Next(0,999999)
printfn "%07i" t
You can do this with a type extension:
type System.Random with
member x.Width w =
x.Next(0, pown 10 w - 1)
|> sprintf "%0*d" w
Here's a few outputs
Random().Width 6;;
val it : string = "985326"
Random().Width 9;;
val it : string = "803426947"
Random().Width 1;;
val it : string = "6"
I know that variables in F# are immutable by default.
But, for example in F# interactive:
> let x = 4;;
val x : int = 4
> let x = 5;;
val x : int = 5
> x;;
val it : int = 5
>
So, I assign 4 to x, then 5 to x and it's changing. Is it correct? Should it give some error or warning? Or I just don't understand how it works?
When you write let x = 3, you are binding the identifier x to the value 3. If you do that a second time in the same scope, you are declaring a new identifier that hides the previous one since it has the same name.
Mutating a value in F# is done via the destructive update operator, <-. This will fail for immutable values, i.e.:
> let x = 3;;
val x : int = 3
> x <- 5;;
x <- 5;;
^^^^^^
stdin(2,1): error FS0027: This value is not mutable
To declare a mutable variable, add mutable after let:
let mutable x = 5;;
val mutable x : int = 5
> x <- 6;;
val it : unit = ()
> x;;
val it : int = 6
But what's the difference between the two, you might ask? An example may be enough:
let i = 0;
while i < 10 do
let i = i + 1
()
Despite the appearances, this is an infinite loop. The i declared inside the loop is a different i that hides the outer one. The outer one is immutable, so it always keeps its value 0 and the loop never ends. The correct way to write this is with a mutable variable:
let mutable i = 0;
while i < 10 do
i <- i + 1
()
x is not changed, it's just hidden by next declaration.
For example:
> let x = 4;;
val x : int = 4
> let x = "abc";;
val x : string = "abc"
>
You're not assigning 5 to x, you are defining a new variable.
The following example shows that there are two distinct variables.
(It also shows that you can "access" the old x if it is in a closure, used by another function):
let x = 5;;
let f y = y+x;;
f 10;;
let x = 0;;
f 10;;
yields
>
val x : int = 5
>
val f : int -> int
> val it : int = 15
>
val x : int = 0
> val it : int = 15
as you see, both calls to f use the first variable x. The definition let x = 0;; defines a new variable x, but does not redefines f.
Here's a minimal example illustrating identifier "shadowing" (i.e. hiding) in F#:
let x = 0
do //introduce a new lexical scope
let x = 1 //"shadow" (i.e. hide) the previous definition of x
printfn "%i" x //prints 1
//return to outer lexical scope
printfn "%i" x //prints 0, proving that our outer definition of x was not mutated by our inner definition of x
Your example is actually a bit more complex, because you are working in the F# Interactive (FSI). FSI dynamically emits code that looks something like the following in your example:
module FSI_0001 =
let x = 4;;
open FSI_0001 //x = 4 is now available in the top level scope
module FSI_0002 =
let x = 5;;
open FSI_0002 //x = 5 is now available in the top level scope, hiding x = 4
module FSI_0003 =
let it = x;;
open FSI_0003
//... subsequent interactions
I have this type:
type Vector3<[<Measure>]'u> =
struct
val x:float32<'u>
val y:float32<'u>
val z:float32<'u>
end
new(x, y, z) = { x = x; y = y; z = z }
When I try to make a default instance, it gives me a strange error that I couldn't find any information on Google about:
Error 5 The default, zero-initializing constructor of a struct type may only be used if all the fields of the struct type admit default initialization
So okay, I can just use the default constructor to set everything to 0 with. Or not.
let f = Vector3(0.f<N>, 0.f<N>, 0.f<N>)
Gives me an error:
Error 1 This expression was expected to have type float32 but here has type float32
This only seems to happen when I use this instance in a subsequent calculation; otherwise, it correctly resolves the type of f as being Vector3<N>. Giving the constructor the type, as in Vector3<N>(...) seems to also solve the problem, which is really strange.
Is there something I'm doing wrong?
There must be something wrong elsewhere in your code. If you reset F# Interactive, open a new empty F# Script file and paste the following code (and then run it in FSI), then everything works just fine for me:
type Vector3<[<Measure>]'u> =
struct
val x:float32<'u>
val y:float32<'u>
val z:float32<'u>
end
new(x, y, z) = { x = x; y = y; z = z }
[<Measure>] type N
let f = Vector3(0.f<N>, 0.f<N>, 0.f<N>)
I would recommend writing the code using implicit constructor syntax which is more succinct and more idiomatic F# (the struct .. end declaration is still allowed, but it has been used mainly in old versions of F#). Default constructor doesn't seem to work in this scenario, but you can use static member:
[<Struct>]
type Vector3<[<Measure>]'u>(x:float32<'u>, y:float32<'u>, z:float32<'u>) =
member this.X = x
member this.Y = y
member this.Z = z
static member Empty : Vector3<'u> = Vector3(0.f<_>, 0.f<_>, 0.f<_>)
[<Measure>] type N
let f1 = Vector3<N>.Empty
let f2 = Vector3(0.f<N>, 0.f<N>, 0.f<N>)
f1.X + f2.X
You need to specify the Default Value attribute for val fields:
type Vector3<[<Measure>]'u> =
struct
[<DefaultValue(false)>] val mutable x:float32<'u>
[<DefaultValue(false)>] val mutable y:float32<'u>
[<DefaultValue(false)>] val mutable z:float32<'u>
end
member X.Init(x,y,z) =
X.x <- x
X.y <- y
X.z <- z
Or use record types:
type Vector3<[<Measure>]'u> = { x : float32<'u>; y : float32<'u> ; z : float32<'u> }
[<Measure>] type N
let v = { x = 10.0F<N>; y = 10.0F<N>; z = 10.0F<N> }
UPDATE:
type Vector3<[<Measure>]'u> =
struct
val x:float32<'u>
val y:float32<'u>
val z:float32<'u>
new(X, Y, Z) = { x = X; y = Y; z = Z }
end
in F#, How to make a function wrapper (x:'T) to wrap any inputs to an array of array, say: wrapper(1) = [|[|1|]|]; wrapper([|1|]) = [|[|1|]|]; and wrapper([|[|1|]|]) = [|[|1|]|]; something like below does not work:
let wrapper (x:'T) =
let y =
if not <| x.GetType().IsArray then [|[|x|]|]
elif not <| x.[0].GetType().IsArray then [|x|]
else x
y
The following seems to work:
let wrapper<'a, 'b> (x:'a) =
match box x with
| null -> null
| :? array<array<'b>> as y -> y
| :? array<'b> as y -> [|y|]
| y -> [|[|unbox y|]|]
The signature is 'a -> array<array<'b>>.
In response to your comment: this sort of thing can be done in statically-typed languages--and, arguably better than in a dynamic language--but/because stepping outside the type system must be explicit (e.g., box/unbox).
Here's a reflection based solution which will accept inputs of arbitrary nested array depth:
open System.Text.RegularExpressions
let wrapper input =
let ty = input.GetType()
if ty.IsArray |> not then
[|[|input |> unbox|]|]
else
let depth = Regex.Matches(ty.Name, "\[\]", RegexOptions.Compiled).Count
let rec findInnerItem curDepth curArray =
let innerItem = curArray.GetType().GetMethod("Get").Invoke(curArray, [|box 0|])
if curDepth = depth then
innerItem
else
findInnerItem (curDepth+1) innerItem
let innerItem = findInnerItem 1 input
[|[|innerItem |> unbox|]|]
Usage in FSI:
val wrapper : 'a -> 'b [] []
> let x : int[][] = wrapper 1;;
val x : int [] [] = [|[|1|]|]
> let x : int[][] = wrapper [|1|];;
val x : int [] [] = [|[|1|]|]
> let x : int[][] = wrapper [|[|1|]|];;
val x : int [] [] = [|[|1|]|]
> let x : int[][] = wrapper [|[|[|1|]|]|];;
val x : int [] [] = [|[|1|]|]
> let x : int[][] = wrapper [|[|[|[|1|]|]|]|];;
val x : int [] [] = [|[|1|]|]
> let x : int[][] = wrapper [|[|[|[|[|1|]|]|]|]|];;
val x : int [] [] = [|[|1|]|]
> let x : int[][] = wrapper [|[|[|[|[|[|1|]|]|]|]|]|];;
val x : int [] [] = [|[|1|]|]
You can't, that's not a well-typed function (try to write out the type signature).
You function needs to "wrap any inputs to an array of array". As par this statement the solution is as simple as:
let wrapper (x:'T) = [|[|x|]|];
But then the examples you have given are not as par your function definition.
i.e wrapper([|1|]) = [|[|1|]|] should be wrapper([|1|]) = [|[|[|1|]|]|] as par your function definition.