System.Array [] not compatible with float [] [] in F#

好久不见. 提交于 2021-02-10 14:26:52

问题


I need to call a function that takes System.Array [] as one parameter in F#. (The function is in a library). I need to pass an argument of type float [] [] [] but the compiler refuses to compile. To replicate the problem, I wrote the following code

let x : float [] [] = Array.init 2 (fun x -> Array.zeroCreate 3)
x :> System.Array;; // This is OK

val x : float [] [] = [|[|0.0; 0.0; 0.0|]; [|0.0; 0.0; 0.0|]|]

> x :> System.Array [];; //Error

  x :> System.Array [];;
  ^^^^^^^^^^^^^^^^^^^^

stdin(14,1): warning FS0059: The type 'System.Array []' does not have any proper subtypes and need not be used as the target of a static coercion

  x :> System.Array [];;
  ^^^^^^^^^^^^^^^^^^^^

stdin(14,1): error FS0193: Type constraint mismatch. The type 
    float [] []    
is not compatible with type
    System.Array []    
The type 'System.Array' does not match the type 'float []'

How can I solve this problem?

Thanks in advance.


回答1:


You could do this:

let x : float [] [] = Array.init 2 (fun x -> Array.zeroCreate 3)

let toArray (xs : #System.Array []) =
    Array.map (fun x -> x :> System.Array) xs

let x' : System.Array [] = toArray x



回答2:


The ability to treat an 's[] as a 't[] when 's :> 't makes the .NET type system unsound (and is probably due to the fact that Java does the same thing). Unfortunately, C# follows .NET in allowing this.

Because it's a .NET runtime feature, you can also do it in F# via boxing and unboxing:

let x : float[][] = Array.init 2 (fun x -> Array.zeroCreate 3)
let x' = (box x) :?> System.Array[]

This avoids the overhead of mapping each element as in Ramon's solution.

To see why this makes the .NET type system unsound, consider this:

x'.[0] <- upcast [| "test" |] // System.ArrayTypeMismatchException

Even though we are storing a value of type System.Array into a System.Array[], we get an exception at runtime because the true type of the underlying array can't support the operation (x and x' are just two views of the same array, and obviously a string[] can't be stored into x). This unsoundness in the .NET type system therefore has the undesirable side effect of requiring additional overhead for most stores into arrays to ensure that the stored value has a type compatible with the underlying array. In my opinion, it's a good thing that F# prevents you from doing this directly.



来源:https://stackoverflow.com/questions/7916212/system-array-not-compatible-with-float-in-f

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!