Tuesday, April 9, 2013

The way to add both indexer and slice to F# sequence

(continued from phosphorescence: Sequence has neither indexer nor slice)

The way to add both indexer and slice to F# sequence is: Expand System.Collections.Generic.IEnumerable on F#.
type System.Collections.Generic.IEnumerable<'a> with
    member this.Item(idx : int) =
        this |> Seq.nth idx
    member this.GetSlice(lower : int option, upper : int option) =
        match lower, upper with
        | Some(lower), Some(upper) -> this |> Seq.skip lower |> Seq.take (upper - lower + 1)
        | Some(lower), None -> this |> Seq.skip lower
        | None, Some(upper) -> this |> Seq.take (upper + 1)
        | None, None -> this

Let's check indexer and slice on Sequence.
> let seq1To5 = seq {1..5};;

val seq1To5 : seq<int>

> seq1To5.[1];;
val it : int = 2
> seq1To5.[0];;
val it : int = 1
> seq1To5.[1..3];;
val it : seq<int> = seq [2; 3; 4]
> seq1To5.[..2];;
val it : seq<int> = seq [1; 2; 3]
> seq1To5.[2..];;
val it : seq<int> = seq [3; 4; 5]
> seq1To5.[*];;
val it : seq<int> = seq [1; 2; 3; 4; ...]
But, list also returns sequense.
> let list1To5 = [1..5];;

val list1To5 : int list = [1; 2; 3; 4; 5]

> list1To5.[0];;
val it : int = 1
> list1To5.[*];;
val it : seq<int> = [1; 2; 3; 4; 5]

So we should define slice for F# list with expanding Microsoft.FSharp.Collections.List.
type Microsoft.FSharp.Collections.List<'a> with
    member this.GetSlice(lower : int option, upper : int option) =
        match lower, upper with
        | Some(lower), Some(upper) -> this |> Seq.skip lower |> Seq.take (upper - lower + 1) |> Seq.toList
        | Some(lower), None -> this |> Seq.skip lower |> Seq.toList
        | None, Some(upper) -> this |> Seq.take (upper + 1) |> Seq.toList
        | None, None -> this
That's all.
> list1To5.[1..3];;
val it : int list = [2; 3; 4]
> list1To5.[2..];;
val it : int list = [3; 4; 5]
> list1To5.[..2];;
val it : int list = [1; 2; 3]
> list1To5.[*];;
val it : int list = [1; 2; 3; 4; 5]

No comments:

Post a Comment