5 people like it.

Recursor

A sugar around IEnumerator<'a> to make it nicer to use with recursive functions

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
module Recursor

type Recursor<'a> (enumerable:System.Collections.Generic.IEnumerable<'a>) =
    let enumerator = enumerable.GetEnumerator ()

    let mutable moreData = enumerator.MoveNext ()

    member __.TryGetValue ([<System.Runtime.InteropServices.OutAttribute>] out:byref<'a>) =
        if moreData then
            out <- enumerator.Current
            true
        else
            false

    member this.Next =
        moreData <- enumerator.MoveNext ()
        this

type System.Collections.Generic.IEnumerable<'a> with
    member this.Recursor = Recursor this

// example
// min_original is (basically) the version in FSharp.Core
// min_recursor is rewritten using this helper

let inline min_original (source:seq<_>) =
    use e = source.GetEnumerator()
    if not (e.MoveNext()) then
        raise (System.ArgumentException ("source", "InputSequenceEmptyString"))
    let mutable acc = e.Current
    while e.MoveNext() do
        let curr = e.Current
        if curr < acc then
            acc <- curr
    acc

let inline min_recursor (source:seq<'a>) =
    let rec minimum (x:Recursor<'a>) first acc =
        match x.TryGetValue () with
        | true, curr when first || curr < acc -> minimum x.Next false curr
        | true, _ -> minimum x.Next false acc
        | false, _ when first -> raise (System.ArgumentException ("source", "InputSequenceEmptyString"))
        | false, _ -> acc
    minimum source.Recursor true Unchecked.defaultof<_>
module Recursor
Multiple items
type Recursor<'a> =
  new : enumerable:IEnumerable<'a> -> Recursor<'a>
  member TryGetValue : out:byref<'a> -> bool
  member Next : Recursor<'a>

Full name: Recursor.Recursor<_>

--------------------
new : enumerable:System.Collections.Generic.IEnumerable<'a> -> Recursor<'a>
val enumerable : System.Collections.Generic.IEnumerable<'a>
namespace System
namespace System.Collections
namespace System.Collections.Generic
type IEnumerable<'T> =
  member GetEnumerator : unit -> IEnumerator<'T>

Full name: System.Collections.Generic.IEnumerable<_>
val enumerator : System.Collections.Generic.IEnumerator<'a>
System.Collections.Generic.IEnumerable.GetEnumerator() : System.Collections.Generic.IEnumerator<'a>
val mutable moreData : bool
System.Collections.IEnumerator.MoveNext() : bool
member Recursor.TryGetValue : out:byref<'a> -> bool

Full name: Recursor.Recursor`1.TryGetValue
namespace System.Runtime
namespace System.Runtime.InteropServices
Multiple items
type OutAttribute =
  inherit Attribute
  new : unit -> OutAttribute

Full name: System.Runtime.InteropServices.OutAttribute

--------------------
System.Runtime.InteropServices.OutAttribute() : unit
val out : byref<'a>
type byref<'T> = (# "<Common IL Type Omitted>" #)

Full name: Microsoft.FSharp.Core.byref<_>
property System.Collections.Generic.IEnumerator.Current: 'a
val this : Recursor<'a>
member Recursor.Next : Recursor<'a>

Full name: Recursor.Recursor`1.Next
val this : System.Collections.Generic.IEnumerable<'T>
Multiple items
member System.Collections.Generic.IEnumerable.Recursor : Recursor<'T>

Full name: Recursor.Recursor

--------------------
type Recursor<'a> =
  new : enumerable:IEnumerable<'a> -> Recursor<'a>
  member TryGetValue : out:byref<'a> -> bool
  member Next : Recursor<'a>

Full name: Recursor.Recursor<_>

--------------------
new : enumerable:System.Collections.Generic.IEnumerable<'a> -> Recursor<'a>
val min_original : source:seq<'a> -> 'a (requires comparison)

Full name: Recursor.min_original
val source : seq<'a> (requires comparison)
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = System.Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
val e : System.Collections.Generic.IEnumerator<'a> (requires comparison)
val not : value:bool -> bool

Full name: Microsoft.FSharp.Core.Operators.not
val raise : exn:System.Exception -> 'T

Full name: Microsoft.FSharp.Core.Operators.raise
Multiple items
type ArgumentException =
  inherit SystemException
  new : unit -> ArgumentException + 4 overloads
  member GetObjectData : info:SerializationInfo * context:StreamingContext -> unit
  member Message : string
  member ParamName : string

Full name: System.ArgumentException

--------------------
System.ArgumentException() : unit
System.ArgumentException(message: string) : unit
System.ArgumentException(message: string, innerException: exn) : unit
System.ArgumentException(message: string, paramName: string) : unit
System.ArgumentException(message: string, paramName: string, innerException: exn) : unit
val mutable acc : 'a (requires comparison)
val curr : 'a (requires comparison)
val min_recursor : source:seq<'a> -> 'a (requires comparison)

Full name: Recursor.min_recursor
val minimum : (Recursor<'a> -> bool -> 'a -> 'a) (requires comparison)
val x : Recursor<'a> (requires comparison)
val first : bool
val acc : 'a (requires comparison)
member Recursor.TryGetValue : out:byref<'a> -> bool
property Recursor.Next: Recursor<'a>
property System.Collections.Generic.IEnumerable.Recursor: Recursor<'T>
module Unchecked

from Microsoft.FSharp.Core.Operators
val defaultof<'T> : 'T

Full name: Microsoft.FSharp.Core.Operators.Unchecked.defaultof

More information

Link:http://fssnip.net/7Uq
Posted:6 years ago
Author:manofstick
Tags: recursion , seq