5

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?

Alexander Sokol
  • 681
  • 4
  • 13
  • Looking at the spec it seems that `matrix.[1 .. 2, 3 .. 4]` is translated into `matrix.GetSlice ((Some(1), Some(2)), (Some(3), Some(4))` so your implementation should take `int option` pairs instead of `int`. – Lee Nov 30 '16 at 11:19

1 Answers1

5

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]
Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553