How can I convert an Int64 to an Int32 type in F# without using the Microsoft.FSharp.Compatibility.Int32.of_int64?
I'm doing this because interactive doesn't seem to work when I try:
open Microsoft.FSharp.Compatibility
With FSharp.PowerPack added as a reference it says:
error FS0039: The namespace 'Compatibility' is not defined.
Edit: Does anyone have an answer to the question? The suggestions about the int types are useful and informative, but I'm having the same issue opening the powerpack namespace in F# interactive.
F# 1.9.6 has a type conversion function so you can do this:
let num = 1000
let num64 = int64(num)
Notice that in this type of conversion, when you reduce the size of a value, the most significant bytes are thrown away, so your data might be truncated:
> let bignum = 4294967297L;;
val bignum : int64
> let myint = int32(bignum);;
val myint : int32
> myint;;
val it : int32 = 1
Note that the functions for converting to each integer type have the same names as the types themselves, and are defined in the library spec (see below). (With the release of the CTP (1.9.6.2), a lot of the library and the namespaces changed a bit compared to previous releases, but it will probably be more 'stable' moving forward.)
http://research.microsoft.com/fsharp/manual/FSharp.Core/Microsoft.FSharp.Core.Operators.html
Related
let a = ref 0
let f (x: byref<int>) = x
f a // type error
System.Int32.TryParse("123",a) // works
f a being a type error is puzzling to me since a can be passed into .NET library methods with a byref<int> type. Why?
Edit: I think I really explained the question poorly. The type of System.Int32.TryParse is string * byref<int> -> bool and yet it works. So why can't I pass a into a function of type x:byref<int> -> int? That is all I am asking.
This feature is described in section 8.13.7 of the F# spec. The ability to use a ref when a byref is expected is enabled by a "type-directed conversion", but these are applied only on member invocations, not on regular function applications.
The only thing I am seeing wrong with that code is the Type Annotation is incorrect, try :int ref instead of byref<int>
Full code:
let a = ref 0
let f (x: int ref) = x
f a // type error
System.Int32.TryParse("123",a) // works
Edit:
Sorry, I misunderstood your question. So this one is a bit vague on F#'s part, I do think F# needs to improve it's error messages a bit. What is happening is since C# did not originally have tuples, they needed out parameters in order to return multiple values. So when you see a signature like byref<int>, that is .NET's way of telling you that is the signature of an out parameter, out parameters are for C# only. More reading here.
I'm just wondering if somebody can explain to me how to pass reference cells to functions that are not class members. I've been following the msdn page msdn reference cells
I have the following code:
let myint = ref 32
let mutable myint2 = 23
type addone() =
member t.myadd1func (x:int byref) =
x <- x + 1
let myadd1func (x:int byref) =
x <- x + 1
let adder = new addone()
adder.myadd1func myint
// myadd1func myint <---- this line does not compile
myadd1func &myint2 // <----- this line does though
printfn "%d" !myint
printfn "%d" myint2
My question is... what is the fundamental difference between the call I am making to the "Myadd1func" method on the class and the "myadd1func" function defined after it?
As I write this, I'm guessing that the function doesn't like having .net object references being passed to it as this might break compatibility with other IL components?? I don't mind using a mutable value, I just like to understand these things.
Thanks
I think the byref type in F# should be used only for interoperability purpsoes where the existing features (as explained by kvb) are good enough. If you want to declare a function that modifies some argument passed to it, I would just use ordinary reference cell (e.g. int ref type):
let myadd1func (x:int ref) =
x := !x + 1
let myint = ref 10
myadd1func myint
This may be slightly slower than using byref type (together with local mutable value), but I don't think it is needed very often in functional style, so it should be fine.
This is explained in the Type-directed Conversions at Member Invocations section of the F# specification. For interoperability with other .NET components, ref cells can be passed to members taking byref parameters and the compiler will automatically treat it as the dereferencing of the cell's contents field. However, this isn't done for let-bound functions, and you should directly use the addressof operator (&). You can still use a ref cell, but you have to explicitly dereference the contents field yourself, so this should work in your example: myadd1func &myint.contents
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 ]
In F#, I'd like to have what I see as a fairly standard Abstract Datatype:
// in ADT.fsi
module ADT
type my_Type
// in ADT.fs
module ADT
type my_Type = int
In other words, code inside the module knows that my_Type is an int, but code outside does not. However, F# seems to have a restriction where type abbreviations specifically cannot be hidden by a signature. This code gives a compiler error, and the restriction is described here.
If my_Type were instead a discriminated union, then there is no compiler error. My question is, why the restriction? I seem to remember being able to do this in SML and Ocaml, and furthermore, isn't this a pretty standard thing to do when creating an abstract datatype?
Thanks
As Ganesh points out, this is a technical limitation of the F# compiler (and .NET runtime), because the type abbreviation is simply replaced by the actual type during the compilation. As a result, if you write a function:
let foo (a:MyType) : MyType = a + 1
The compiler will compile it as a .NET method with the following signature:
int foo(int a);
If the actual type of the abbreviation was hidden from the users of the library, then they wouldn't be able to recognize that the foo function is actually working with MyType (this information is probably stored in some F#-specific meta-data, but that is not accessible to other .NET languages...).
Perhaps the best workaround for this limiation is to define the type as a single-case discriminated union:
type MyType = MT of int
let foo (MT a) = MT(a + 1)
Working with this kind of type is quite convenient. It adds some overhead (there are new objects created when constructing a value of the type), but that shouldn't be a big issue in most of the situations.
Type abbreviations in F# are compiled away (i.e. the compiled code will use int, not MyType), so you can't make them properly abstract. In theory the compiler could enforce the abstraction within the F# world, but this wouldn't be very helpful as it would still leak in other languages.
Note that you can define a type abbreviation as private within a module:
// File1.fs
module File1
type private MyType = int
let e : MyType = 42
let f (x:MyType) = x+1
// Program.fs
module Program
do printfn "%A" (File1.f File1.e)
I am unclear why you can't hide it with a signature; I logged a bug to consider it.
From what I understand F# does not allow an abbreviation to be hidden by a signature.
I found this link where the blogger commented on this but I am not sure on the specifics of why this is the case.
My assumption is that this is a restraint set to allow more effective interop with other languages on the CLR.
I was using the Pow function of the BigInteger class in F# when my compiler told me :
This construct is deprecated. This member has been removed to ensure that this
type is binary compatible with the .NET 4.0 type System.Numerics.BigInteger
Fair enough I guess, but I didn't found a replacement immediately.
Is there one? Should we only use our own Pow functions? And (how) will it be replaced in NET4.0?
You can use the pown function
let result = pown 42I 42
pown works on any type that 'understands' multiplication and 'one'.
If you look at F# from the perspective of being based on OCaml, then the OCaml Num module has power_num. Since OCaml type num are arbitrary-precision rational numbers they can handle any size number, e.g. they are not limited by the CPU register because they can do the math symbolically. Also since num is defined as
type num =
| Int of int
| Big_int of Big_int.big_int
| Ratio of Ratio.ratio
they can handle very small numbers with out loss of precision because of the Ratio type.
Since F# does not have the num type, Jack created the FSharp.Compatibility.OCaml module which has num.fs and is available via NuGet.
So you can get all the precision you want using this, and the num functions can handle negative exponents.