Ricerca…


Introduzione alle pieghe, con una manciata di esempi

Le pieghe sono funzioni (di ordine superiore) utilizzate con sequenze di elementi. Crollano seq<'a> in 'b dove 'b è di qualsiasi tipo (eventualmente ancora 'a ). Questo è un po 'astratto, quindi lasciate entrare in esempi pratici concreti.

Calcolo della somma di tutti i numeri

In questo esempio, 'a è un int . Abbiamo una lista di numeri e vogliamo calcolare sommarne tutti i numeri. Per sommare i numeri della lista [1; 2; 3] scriviamo

List.fold (fun x y -> x + y) 0 [1; 2; 3] // val it : int = 6

Lasciatemi spiegare, perché abbiamo a che fare con le liste, usiamo la fold nel modulo List , quindi List.fold . il primo argomento fold takes è una funzione binaria, la cartella . Il secondo argomento è il valore iniziale . fold inizia a piegare la lista applicando consecutivamente la funzione cartella agli elementi della lista iniziando dal valore iniziale e dal primo elemento. Se la lista è vuota, viene restituito il valore iniziale!

La panoramica schematica di un esempio di esecuzione si presenta così:

let add x y = x + y // this is our folder (a binary function, takes two arguments)
List.fold add 0 [1; 2; 3;]
=> List.fold add (add 0 1) [2; 3] 
// the binary function is passed again as the folder in the first argument
// the initial value is updated to add 0 1 = 1 in the second argument
// the tail of the list (all elements except the first one) is passed in the third argument
// it becomes this:
List.fold add 1 [2; 3]
// Repeat untill the list is empty -> then return the "inital" value
List.fold add (add 1 2) [3]
List.fold add 3 [3] // add 1 2 = 3
List.fold add (add 3 3) [] 
List.fold add 6 [] // the list is empty now -> return 6
6

La funzione List.sum è approssimativamente List.fold add LanguagePrimitives.GenericZero dove lo zero generico lo rende compatibile con interi, float, interi grandi ecc.

Conteggio degli elemets in un elenco ( count dell'implementazione)

Questo viene fatto quasi come sopra, ma ignorando il valore reale dell'elemento nella lista e aggiungendo invece 1.

List.fold (fun x y -> x + 1) 0 [1; 2; 3] // val it : int = 3

Questo può anche essere fatto in questo modo:

[1; 2; 3]
|> List.map (fun x -> 1) // turn every elemet into 1, [1; 2; 3] becomes [1; 1; 1]
|> List.sum // sum [1; 1; 1] is 3

Quindi puoi definire il count come segue:

let count xs = 
    xs 
    |> List.map (fun x -> 1) 
    |> List.fold (+) 0 // or List.sum

Trovare il massimo della lista

Questa volta useremo List.reduce che è come List.fold ma senza un valore iniziale come in questo caso in cui non sappiamo quale sia il tipo dei valori che stiamo confrontando:

let max x y = if x > y then x else y
// val max : x:'a -> y: 'a -> 'a when 'a : comparison, so only for types that we can compare
List.reduce max [1; 2; 3; 4; 5] // 5
List.reduce max ["a"; "b"; "c"] // "c", because "c" > "b" > "a"
List.reduce max [true; false] // true, because true > false 

Trovare il minimo di una lista

Proprio come quando si trova il massimo, la cartella è diversa

let min x y = if x < y then x else y
List.reduce min [1; 2; 3; 4; 5] // 1
List.reduce min ["a"; "b"; "c"] // "a"
List.reduce min [true; false] // false

Elenchi concatenanti

Qui stiamo prendendo l'elenco delle liste La funzione cartella è l'operatore @

// [1;2] @ [3; 4] = [1; 2; 3; 4]
let merge xs ys = xs @ ys
List.fold merge [] [[1;2;3]; [4;5;6]; [7;8;9]] // [1;2;3;4;5;6;7;8;9]

Oppure potresti usare gli operatori binari come funzione della tua cartella:

List.fold (@) [] [[1;2;3]; [4;5;6]; [7;8;9]] // [1;2;3;4;5;6;7;8;9]
List.fold (+) 0 [1; 2; 3] // 6
List.fold (||) false [true; false] // true, more on this below
List.fold (&&) true [true; false] // false, more on this below
// etc...

Calcolo del fattoriale di un numero

La stessa idea di quando si sommano i numeri, ma ora li moltiplichiamo. se vogliamo il fattoriale di n moltiplessiamo tutti gli elementi nella lista [1 .. n] . Il codice diventa:

// the folder
let times x y = x * y
let factorial n = List.fold times 1 [1 .. n]
// Or maybe for big integers
let factorial n = List.fold times 1I [1I .. n] 

Implementare forall , exists e contains

la funzione forall controlla se tutti gli elementi di una sequenza soddisfano una condizione. exists controllo se almeno un elemento nell'elenco soddisfa la condizione. Per prima cosa dobbiamo sapere come comprimere un elenco di valori bool . Bene, usiamo le pieghe ofcourse! gli operatori booleani saranno le nostre funzioni di cartella.

Per verificare se tutti gli elementi in una lista sono true , li collassiamo con la funzione && con true come valore iniziale.

List.fold (&&) true [true; true; true] // true
List.fold (&&) true [] // true, empty list -> return inital value
List.fold (&&) true [false; true] // false

Allo stesso modo, per verificare se un elemento è true in una lista di valori booleani, lo collassiamo con || operatore con false come valore iniziale:

List.fold (||) false [true; false] // true
List.fold (||) false [false; false] // false, all are false, no element is true
List.fold (||) false [] // false, empty list -> return inital value

Torna a forall ed exists . Qui prendiamo una lista di qualsiasi tipo, usiamo la condizione per trasformare tutti gli elementi in valori booleani e poi la comprimiamo:

let forall condition elements = 
    elements 
    |> List.map condition // condition : 'a -> bool
    |> List.fold (&&) true

let exists condition elements = 
    elements
    |> List.map condition
    |> List.fold (||) false

Per verificare se tutti gli elementi in [1; 2; 3; 4] sono più piccoli di 5:

forall (fun n -> n < 5) [1 .. 4] // true

definire il metodo contains con exists :

let contains x xs = exists (fun y -> y = x) xs

O anche

let contains x xs = exists ((=) x) xs

Ora controlla se la lista [1 .. 5] contiene il valore 2:

contains 2 [1..5] // true

Attuazione al reverse :

let reverse xs = List.fold (fun acc x -> x :: acc) [] xs
reverse [1 .. 5] // [5; 4; 3; 2; 1]

Implementazione di map e filter

let map f = List.fold (fun acc x -> List.append acc [f x]) List.empty
// map (fun x -> x * x) [1..5] -> [1; 4; 9; 16; 25]   

let filter p = Seq.fold (fun acc x -> seq { yield! acc; if p(x) then yield x }) Seq.empty
// filter (fun x -> x % 2 = 0) [1..10] -> [2; 4; 6; 8; 10]

C'è qualcosa fold non si può fare? Non lo so davvero

Calcolo della somma di tutti gli elementi di una lista

Per calcolare la somma di termini (di tipo float, int o intero grande) di un elenco di numeri, è preferibile utilizzare List.sum In altri casi, List.fold è la funzione più adatta per calcolare tale somma.

  1. Somma di numeri complessi

In questo esempio, dichiariamo un elenco di numeri complessi e calcoliamo la somma di tutti i termini nell'elenco.

All'inizio del programma, aggiungi un riferimento a System.Numerics

apri System.Numerics

Per calcolare la somma, inizializziamo l'accumulatore al numero complesso 0.

let clist = [new Complex(1.0, 52.0); new Complex(2.0, -2.0); new Complex(0.0, 1.0)]

let sum = List.fold (+) (new Complex(0.0, 0.0)) clist

Risultato:

(3, 51)
  1. Somma dei numeri di tipo di unione

Supponiamo che una lista sia composta da numeri di tipo union (float o int) e voglia calcolare la somma di questi numeri.

Dichiarare prima del seguente tipo di numero:

type number = 
| Float of float
| Int of int

Calcola la somma dei numeri del numero di tipo di una lista:

let list = [Float(1.3); Int(2); Float(10.2)]

let sum = List.fold (
                         fun acc elem -> 
                                        match elem with
                                        | Float(elem) -> acc + elem
                                        | Int(elem) -> acc + float(elem)
                        ) 0.0 list

Risultato:

13.5

Il primo parametro della funzione, che rappresenta l'accumulatore, è di tipo float e il secondo parametro, che rappresenta un elemento nell'elenco, è di tipo numero. Ma prima di aggiungere, dobbiamo usare un pattern matching e cast per digitare float quando elem è di tipo Int.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow