Passando attraverso le linee, riga per riga, in modo da poter meglio capire meglio:
1| maximum' :: (Ord a) => [a] -> a
2| maximum' [] = error "maximum of empty list"
3| maximum' [x] = x
4| maximum' (x:xs)
| x > maxTail = x
| otherwise = maxTail
where maxTail = maximum' xs
In linea 1: si dice che si ottiene un elenco di di e restituire un elemento di quel tipo. Inoltre, gli elementi di quella lista devono essere ordinati, quindi puoi metterli in un ordine.
Nella riga 2: si ha un caso limite, dove si dice che se si ottiene una lista vuota come input, non ci può essere un "valore più alto" in quella lista vuota, quindi si termina la funzione con un errore .
Nella riga 3: si ha un altro caso limite, in cui si dice che se si ottiene un elenco con 1 elemento, quell'elemento deve essere l'elemento più alto, quindi lo si restituisce.
Nella riga 4: si utilizza la corrispondenza del modello per abbinare il primo elemento (x
) e il resto dell'elenco (xs
). Quindi si controlla se maxTail
è più grande di maxTail
, dove è il risultato della chiamata di funzione maximum'
con il resto dell'elenco xs
.
Se questo x
è più grande maxTail
poi ritorni x
ed altrimenti maxTail
è più grande di x
e ritorni maxTail
.
penso che un esempio con alcuni numeri dovrebbe anche aiutare qui:
ingresso:
[2, 5, 4, 13]
chiamata:
maximum' [2, 5, 4, 13]
Cosa succede:
maximum' (x : xs)
↓ ↓
maximum' (2:[5, 4, 13])
│
↓ result 13
x > maxTail = x ↑
2 > maximum' [5, 4, 13] = x //2 > 13 = 13 ← ────┐
│ │
└ maximum' (x : xs) │
↓ ↓ │
maximum' (5:[4, 13]) │
│ │
↓ ↑
x > maxTail = x │
5 > maximum' [4, 13] = x //5 > 13 = 13 ← ─────┐
│ │
└ maximum' (x: xs) │
↓ ↓ │
maximum' (4:[13]) │
│ │
↓ ↑
x > maxTail = x │
4 > maximum' [13] = x //4 > 13 = 13 ┐
│ │
└ maximum' [x] = x ↑
maximum' [13] = 13 → ───────────┘
Nel suo secondo esempio è più o meno lo stesso:
1| reverse' :: [a] -> [a]
2| reverse' [] = []
3| reverse' (x:xs) = reverse' xs ++ [x]
In linea 1: si dice che si ottiene un elenco di di e restituire un elenco di di.
Nella riga 2: si ha un caso limite, dove si dice se si ottiene una lista vuota, l'elenco invertito è anche solo vuoto.
Nella riga 3: si utilizza nuovamente la corrispondenza del modello per abbinare il primo elemento (x
) dell'elenco e la coda (xs
) di esso.
Ora basta usare ++
per aggiungere due elenchi, che è il primo elemento della lista con la coda invertita.
E di nuovo mi auguro con un esempio che sarà un po 'più chiaro:
ingresso:
[1, 2, 3]
chiamata:
reverse' [1, 2, 3]
Cosa succede:
reverse' (x : xs)
↓ ↓
reverse' (1:[2, 3])
│ result [3, 2, 1]
↓ ↑
(reverse' [2, 3]) ++ [1] //[3, 2] ++ [1] = [3, 2, 1] ← ────┐
│ │
└ reverse' (x: xs) │
↓ ↓ │
reverse' (2:[3]) │
│ ↑
↓ │
(reverse' [3]) ++ [2] //[3] ++ [2] = [3, 2] ← ───┐ → ┘
│ │
└ reverse' (x:xs) │
↓ ↓ │
reverse' (3:[]) │
│ ↑
↓ │
(reverse' []) ++ [3] //[] ++ [3] = [3] ┐ → ┘
│ ↑
└ reverse' [] = [] → ──────────────────┘
'reverse'' non significa "invertire gli elementi di coda". 'reverse 'xs' significa" inverti gli elementi di coda ", perché' xs' è gli elementi di coda e' reverse 'significa invertire. – immibis
Si noti che nel caso ricorsivo, le funzioni 'maximum'' e' reverse'' sono chiamate su _tail_ (cioè tutto tranne il primo elemento) della lista data, ad es. 'maximum '[1,2,3]' è applicato in modo ricorsivo sulla lista '[2,3]'. L'idea è che il massimo di un elenco di numeri interi è il valore maggiore di 1. il primo elemento dell'elenco e 2. il massimo del resto dell'elenco. Quando si abbina il modello in una lista tramite '(x: xs)', 'x' è il primo elemento della lista e' xs' è il resto (la "coda"). –
"come fa a sapere che la retromarcia" significa invertire gli elementi delle code. " non è così; ma puoi provarlo per induzione. Inizia con i casi '[]' e '[a]'; quindi controlla '[a, b]', ...., quindi assumi che valga per il caso generale '[a, b, ..., n]' e dimostra che segue il caso successivo, '[ a, b, ..., n, m] ', si sta invertendo anche. –