29 people like it.

Extensions to the Fold function

This snippet is helpfull in the following cases: 1) After a consolidation operation using the fold function we need to know how many elements have been processed. 2) A consolidation operation needs to use the index of each of the elements processed and we don't want to use the mapi function first. 3) A combination of the above. Since the following snippet just adds a wrapper to the existing Fold function we can repeat the approach for arrays and sequences (including the plinq ones)

Extending the Fold function in terms of itself

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
module List =

    //Executes a fold operation within a list returning a two-dimension tuple with
    //the first element being the result of the fold and the second being the count of the
    //processed elements.
    let public foldc fold first source  =
       source 
       |> List.fold(fun (prev,count) c -> (fold prev c,count + 1)) (first,0)

    //Executes a fold operation within a list passing as parameter of the folder function 
    //the zero based index of each element.
    let public foldi fold first source  =
       source 
       |> List.fold(fun (prev,i) c -> (fold i prev c,i + 1)) (first,0)
       |> fst

    //Executes a fold operation within a list passing as parameter of the folder function 
    //the zero based index of each element and returning a two-dimension tuple with
    //the first element being the result of the fold and the second being the count of the
    //processed elements.
    let public foldic fold first source  =
        source 
        |> List.fold(fun (prev,i) c -> (fold i prev c, i + 1)) (first,0)

Examples

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
let foldc_result = [1 .. 9] 
                   |> List.foldc (+) 0
                   //(45,9)

let foldi_result = [1 .. 9] 
                   |> List.foldi (fun i (s1,s2) c -> (s1 + (2.0 ** float c), 
                                                      s2 + (2.0 ** float i))) (0.0,0.0) 
                   //(1022.0, 511.0)

let foldic_result = [1 .. 9] 
                   |> List.foldic (fun i (s1,s2) c -> (s1 + (2.0 ** float c), 
                                                       s2 + (2.0 ** float i))) (0.0,0.0) 
                    //(1022.0, 511.0,9)        
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
  interface IEnumerable
  interface IEnumerable<'T>
  member Head : 'T
  member IsEmpty : bool
  member Item : index:int -> 'T with get
  member Length : int
  member Tail : 'T list
  static member Cons : head:'T * tail:'T list -> 'T list
  static member Empty : 'T list

Full name: Microsoft.FSharp.Collections.List<_>
val foldc : fold:('a -> 'b -> 'a) -> first:'a -> source:'b list -> 'a * int

Full name: Script.List.foldc
val fold : ('a -> 'b -> 'a)
val first : 'a
val source : 'b list
val fold : folder:('State -> 'T -> 'State) -> state:'State -> list:'T list -> 'State

Full name: Microsoft.FSharp.Collections.List.fold
val prev : 'a
val count : int
val c : 'b
val foldi : fold:(int -> 'a -> 'b -> 'a) -> first:'a -> source:'b list -> 'a

Full name: Script.List.foldi
val fold : (int -> 'a -> 'b -> 'a)
val i : int
val fst : tuple:('T1 * 'T2) -> 'T1

Full name: Microsoft.FSharp.Core.Operators.fst
val foldic : fold:(int -> 'a -> 'b -> 'a) -> first:'a -> source:'b list -> 'a * int

Full name: Script.List.foldic
val foldc_result : int * int

Full name: Script.foldc_result
Multiple items
module List

from Script

--------------------
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
  interface IEnumerable
  interface IEnumerable<'T>
  member Head : 'T
  member IsEmpty : bool
  member Item : index:int -> 'T with get
  member Length : int
  member Tail : 'T list
  static member Cons : head:'T * tail:'T list -> 'T list
  static member Empty : 'T list

Full name: Microsoft.FSharp.Collections.List<_>
val foldi_result : float * float

Full name: Script.foldi_result
val s1 : float
val s2 : float
val c : int
Multiple items
val float : value:'T -> float (requires member op_Explicit)

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

--------------------
type float = System.Double

Full name: Microsoft.FSharp.Core.float

--------------------
type float<'Measure> = float

Full name: Microsoft.FSharp.Core.float<_>
val foldic_result : (float * float) * int

Full name: Script.foldic_result

More information

Link:http://fssnip.net/2Z
Posted:6 years ago
Author:Horacio Nuñez
Tags: lists , sequences , arrays , extension , fold