F #: Downcast seq to IEnumerator

Why is it in F #, I can do it ...

let s = seq { for i in 0 .. 4095 do yield i } :?> IEnumerator

... but does it cause a System.InvalidCastException?

let s = Seq.init 4095 (fun i -> i) :?> IEnumerator
+4
source share
2 answers

The sequence expression creates an object that implements IEnumerable<T>andIEnumerator<T>

let s = seq { for i in 0 .. 4095 do yield i }
printfn "%b" (s :? IEnumerable<int>) // true
printfn "%b" (s :? IEnumerator<int>) // true

But Seq.initnot:

let s = Seq.init 4095 (fun i -> i)
printfn "%b" (s :? IEnumerable<int>) // true
printfn "%b" (s :? IEnumerator<int>) // false

You can reorganize your code to use IEnumerable<T>instead IEnumerator, as both constructs create IEnumerable<T>.

Alternatively, if you really want to IEnumerator, you can simply call GetEnumeratorto return Enumeratorfrom Enumerable:

let s = (Seq.init 4095 (fun i -> i)).GetEnumerator()
printfn "%b" (s :? IEnumerable<int>) // false
printfn "%b" (s :? IEnumerator<int>) // true
+6
source

, :

Seq.collect (fun pat -> Seq.singleton(pat)) (0 .. 4095)

Seq.collect, :

let collect f sources = map f sources |> concat

concat, :

let concat sources = 
            checkNonNull "sources" sources
            mkConcatSeq sources

mkConcatSeq :

let mkConcatSeq (sources: seq<'U :> seq<'T>>) = 
            mkSeq (fun () -> new ConcatEnumerator<_,_>(sources) :> IEnumerator<'T>)

, IEnumerator<'T> , , IEnumerator.

Seq.init :

let init count f =
            if count < 0 then invalidArg "count" (SR.GetString(SR.inputMustBeNonNegative))
            mkSeq (fun () -> IEnumerator.upto (Some (count-1)) f)

mkSeq :

let mkSeq f = 
            { new IEnumerable<'U> with 
                member x.GetEnumerator() = f()
              interface IEnumerable with 
                member x.GetEnumerator() = (f() :> IEnumerator) }

IEnumerable<'T>, IEnumerator.

+5

Source: https://habr.com/ru/post/1537016/


All Articles