Cast array to object - f#

I have an array and I want to cast it to an object. This is my code.
let a = [| 1 |]
let b = a :?> obj
but it tells me that int [] has no proper subtypes and cannot be used as a source of runtime type coercion. I'm pretty sure I can always do (object) in C# without the compiler complaining, so what's the issue here?

You're trying to downcast (:?>), instead of upcast (:>). Your code should be:
let a = [| 1 |]
let b = a :> obj
Please see http://msdn.microsoft.com/en-us/library/dd233220.aspx for more details.

While ebb's answer is of course correct, there is another solution for the special case of upcasting to obj, which is the box operator:
let a = [| 1 |]
let b = box a
In F#, box doesn't have the same meaning as it does in the CLR, where it means "make a reference-type object corresponding to a value-type value." In F#, it just means "cast to obj." Because of this, you can use box with reference types as well as with value types.

Related

F# value restriction problem in reversing list

The following F# code doesn't compile due to value restriction problem:
let x = List.rev []
But this compiles:
let x = List.rev [] in 3::x
As I understand it, the compiler infers that x must be of type int list so it doesn't compile.
The following doesn't compile:
let x = List.rev [] in (3::x, true::x)
But this does:
let x = ([]) in (3::x, true::x)
Why?
As I understand it*, there are two ways to declare a value in F#:
Value has a concrete type (e.g. List<int>). You must either explicitly specify this concrete type, or the compiler must be able to infer it.
Value has a generic type (e.g. List<'t>). You must either explicitly specify this generic type, or the compiler must be able to infer it and the value must be a simple immutable value.
With that in mind, here are the explanations for what you're seeing:
// not allowed because x is generic, but not simple
let x = List.rev []
// allowed because the compiler can infer x's concrete type (List<int>)
let x = List.rev [] in 3::x
// not allowed because x is generic, but not simple
let x = List.rev [] in (3::x, true::x)
// allowed because x is both generic and simple (compiler can tell it's the empty list)
let x = ([]) in (3::x, true::x)
* The value restriction can be tricky, so there may be nuances I've overlooked in my explanation.

Explanation and idiomatic solution(s) for assignments to arrays in classes in F#

I've been trying out F# a bit recently, but I've almost exclusively used records and immutability. Now I'm trying mutable classes, however, and it's giving me some issues.
The biggest one so far is that it seems I can't assign to an element of an array that is a member of a class. For example, the following works as expected, replacing the 0th element with a 9:
let array = [| 0..5 |]
array.[0] <- 9
printfn "%A" array
However, this does not work as I would expect:
type MyClass () =
member this.Array = [| 0..5 |]
let myClass = MyClass()
myClass.Array.[0] <- 9
printfn "%A" myClass.Array
The assignment seems to do nothing, but the compiler does not complain with even a warning. I assume there is something that prevents assignments to members of classes, including their submembers and elements, but I can't find any documentation or outside explanations of it.
Could someone help me understand what's going on here and give an example or two of how this is typically done?
MyClass.Array, the way you declared it, is a readonly property. You gave it a get accessor, and the body of that accessor consists of creating an array and returning it.
Spot the problem yet? It's a new array every time you call MyClass.Array. The first array does get mutated just fine, but then you just throw it away and request a new array from the class.
If you want to "store" an array "inside" the class, you need to give it a name, and then make your property accessor refer to that name. That way, the property accessor will return the same array every time:
type MyClass() =
let theArray = [|0..5|]
member this.Array = theArray
(incidentally, this very gotcha is one of the reasons to avoid mutable data)
This is probably because the declaration you have defines this.Array as a read-only property. As mentioned in another answer, the code you have returns a new array for each call.
An auto property works and is a little more concise:
type MyClass () =
member val Array = [| 0..5 |] with get,set
let myClass = MyClass()
myClass.Array.[0] <- 9
printfn "%A" myClass.Array // [|9; 1; 2; 3; 4; 5|]

When a function with seq type parameter is a record field, it won't accept list or array any more

Please see the below code.
let x = Seq.head [1.0; 2.0] // This is ok.
type Func<'T> = { f: seq<'T> -> 'T }
let func = { f = Seq.head }
// Compilation error: This expression was expected to have type seq<obj> but here has type 'a list
let y = func.f [1.0; 2.0]
let z = func.f ([1.0; 2.0] |> List.toSeq) // This is ok.
I don't understand why Seq.head and fund.f behavior differently here. It looks like a compiler bug to me. However, if this is by design, can anyone help explain a little bit to me? Thanks a lot!
The below is the answer from Don Syme (github.com/fsharp):
This is by design. The rule called "14.4.3 Implicit Insertion of Flexibility for Uses of Functions and Members" is only applied to uses of functions and members, not uses of record fields.

F# cons operator and list in class

So here is my question. I have a python project that is very functionally oriented...but which fundamentally runs with classes...so F# seemed the ideal language for a compiled version of my code (I'd like to black box my source code...the python code is just sitting there in files. Not cool).
In my python class, I have a generic container--a python list. This container will contain arrays of a uniform length in a given implementation...
Here is my problem: I need to add arrays to the list after initialization.
What is the proper way to add arrays to the list in the class?
Here is what I have...but it seems like it will be slow, since it throws out the old list with a new copy (right??):
type myclass() =
let mutable _training = []
member this.training with get() = _training
and set(value) = _training <- value::_training
However, this fails (even after the edits suggested below) because the compiler claims that the set function is an obj with set rather than an obj list with set, even though it acknowledges that _training is a mutable obj list on the left side of the <- in the set function...I'm stumped)
What is the proper "F#" way to do this?
The 'proper' F# way to do it is to not have that myclass class at all. A class with a single getter and setter provides no value over an immutable list.
That said, the above code doesn't compile for a number of reasons:
A type is defined with =, not :.
_training isn't bound by with a let expression.
If you want to mutate the _training value, you must declare it let mutable
Even so, the return value of get is obj list, but the input value of set (which is the symbol value) is obj, because of the use of the cons operator (::). As the compiler says, the type of get and set must be the same.
You can make it compile by addressing all these concerns:
type Myclass() =
let mutable _training = []
member this.training with get() = _training
and set(value) = _training <- value
but it would accomplish nothing. If you need a list, then pass a list. It's not that we don't believe in encapsulation in F#, but properties aren't equivalent to encapsulation anyway...
BTW, it'd be idiomatic to name types using Pascal Case, so MyClass instead of myclass. The leading underscore isn't used much either, so it should be training instead of _training.
The problem is that a property has a type,
and the getter and setter must be compatible with that type.
If I run your code interactively, the compiler helpfully tells me exactly that!
type myclass() =
let mutable _training = []
member this.training
with get() = _training
and set(value) = _training <- value::_training
// error FS3172: A property's getter and setter must have the same type.
// Property 'training' has getter of type 'obj list'
// but setter of type 'obj'.
The answer is simply to have a different method that prepends an element
to the list:
type myclass() =
let mutable _training = []
member this.training
with get() = _training
and set(newTraining) = _training <- newTraining
member this.prepend(element) =
_training <- (element::_training)
member this.prependList(list) =
_training <- (list # _training)
// test
let myList = myclass()
myList.prepend(1)
myList.prepend(2)
myList.training // output => [2; 1]
myList.prependList([3;4])
myList.training // output => [3; 4; 2; 1]
It's not a nice implementation from a functional point of view,
but it does answer your question.
Note that if you do want a pure functional implementation,
you don't need a class at all.
// test
let myList = []
let myList2 = 1::myList
let myList3 = 2::myList2
// myList3 => [2; 1]
let myList4 = [3;4] # myList3
// myList4 => [3; 4; 2; 1]
Now, how to work with immutable state in a nice way -- that's a whole
other question! :)

Why am I not allowed to use reference cell as argument for byref parameter in let functions?

This doesn't work:
let increment(i: int byref) = i <- i + 1
let xxx = ref 0
increment(xxx) // this expression was expected to have type
// byref<int> but here has type int ref
But this works:
let incrementParam(a: int byref) = a <- a + 1
let mutable b = 30
incrementParam(&b)
as well as this:
type Incrementor =
static member Increment(i : int byref) =
i <- i + 1
let fff = ref 10
Incrementor.Increment(fff)
Because the spec says so. See Type Directed Conversions at Member Invocations (emphasis mine), especially the following:
Note: These type-directed conversions are primarily for interoperability with existing member-based .NET libraries and do not apply at invocations of functions defined in modules or bound locally in expressions.
To add some details to the reference that Daniel pointed out, the problem is that the type 'T ref is not the same as the type 'T byref and so the compiler needs to insert some conversion (to take the address).
I think this is only supported for members, because this is the main scenario (calling COM interop methods etc.) and because implicit conversions generally compilcate type inference. The type-directed conversions are an easier case where the compiler already knows the required type ('T byref). I suppose that, if this was allowed on functions, the compiler might infer that the type of argument should actually be 'T ref.
If you want to get the first sample to work, you have to explicitly construct 'T byref by taking the address of the contents field:
let increment(i: int byref) = i <- i + 1
let xxx = ref 0
increment(&xxx.contents)

Resources