Reputation: 669
I'm trying to make a type that should represent a "slice" of some indexable collection.
I know that there are some similar types in F# but not one that specifies the criteria that I need.
To do this it needs to carry a reference to the collection of type 'content and the content needs to be indexable. So I tried this constraint since a type only needs to have the member Item (get/set) so I tried this
type Slice<'a, 'content when 'content: (member Item: int -> 'a)>
This still throw the usual error
So is it possible to constrain a type to still be generic but constraint to be indexable?
Upvotes: 1
Views: 86
Reputation: 17038
I think something like this should work:
type Slice<'a, 'content when 'content: (member get_Item: int -> 'a)> =
{
Content : 'content
Start : int
Stop : int
}
with
member inline slice.get_Item(i) =
slice.Content.get_Item(slice.Start + i)
I've implemented get_Item
on Slice
as well, so you can take a slice of a slice. Here are some values of this type:
let strSlice =
{
Content = "hello"
Start = 1
Stop = 2
}
let arraySlice =
{
Content = [| 2; 4; 6; 8 |]
Start = 0
Stop = 3
}
let strSliceSlice =
{
Content = strSlice
Start = 0
Stop = 1
}
Upvotes: 2
Reputation: 669
[<Interface>]
type Indexable<'a> =
abstract member Item: int -> 'a with get
[<Struct>]
type Slice<'a> =
{
content: Indexable<'a>
start: int
len: int
}
with
interface Indexable<'a> with
member I.Item with get(i) = I.[idx]
member S.Item with get(idx) =
if idx >= S.len
then raise(IndexOutOfRangeException())
else S.content.[S.start+idx]
This works.
Upvotes: 0