F# supports "slice expressions", which e.g. for a conventional one-dimensional array myArray
allows for expressions such as myArray.[3 .. 5]
. According to e.g. the F# 4.0 language specification (section 6.4.7), this is implemented by calling a GetSlice method after appropriate conversion of parameters. This also works for multidimensional arrays. However, I'm having some trouble defining an interface implementing this in the two-dimensional case.
What I've done is the following. I've defined an interface as follows:
type IMatrix =
abstract member GetSlice : ?start1:int * ?end1:int * ?start2:int * ?end2:int -> IMatrix
abstract member GetSlice : idx1:int * ?end1:int * ?start2:int * ?end2:int -> IMatrix
abstract member GetSlice : ?start1:int * ?end1:int * idx2:int -> IMatrix
This is based on the instructions as I understood them from section 6.4.7 of the specification. The idea is that when I then have an IMatrix
named matrix
, I should be able to write
matrix.[1 .. 2, 3 .. 4]
and get a submatrix of type IMatrix
. The idea is that essentially, 1 .. 2
gets converted to Some 1, Some 2
and 3 .. 4
gets converted to Some 3, Some 4
by the compiler, and those four option types are given the the four-parameter GetSlice
method.
However, when I try this in practice, the compiler reports errors that no overloads match for method 'GetSlice', in particular mentioning that the type 'int' is not compatible with the type 'int option'. It thus seems to me that the compiler correctly infers that the slice notion should be converted to a GetSlice call, but somehow the arguments get mixed up.
As an aside, I get the same problem if I try this when implementing a one-dimensional slicing for e.g. an IVector interface, or when trying this out on a class instead of an interface.
How do I fix this?
I think the compiler just requires the parameters to be explicitly of type int option
rather than being optional parameters of type int
. The following type checks:
type IMatrix =
abstract member GetSlice :
start1:int option * end1:int option *
start2:int option * end2:int option -> IMatrix
abstract member GetSlice :
idx1:int *
start2:int option * end2:int option -> IMatrix
abstract member GetSlice :
start1:int option * end1:int option *
idx2:int -> IMatrix
let m : IMatrix = failwith "!"
m.[1 .. 2, 3 .. 4]
m.[1, 3 .. 4]
m.[1 .. 2, 3]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With