Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing GetSlice for slicing in F# interface

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?

like image 446
Alexander Sokol Avatar asked Nov 30 '16 10:11

Alexander Sokol


1 Answers

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]
like image 72
Tomas Petricek Avatar answered Nov 07 '22 06:11

Tomas Petricek