2015-07-27 11 views
7

Sto giocando con il linguaggio per iniziare l'apprendimento e sono perplesso oltre la mia intelligenza su come funziona una definizione ricorsiva.Come funziona (co) la definizione ricorsiva in Haskell?

Per esempio, prendiamo la sequenza dei numeri triangolari (TN n = sum [1..n])

La soluzione fornita era:

triangularNumbers = scanl1 (+) [1..] 

Fin qui, tutto bene.

Ma la soluzione sono venuto su con era:

triangularNumbers = zipWith (+) [1..] $ 0 : triangularNumbers 

che è anche corretto.

Ora la mia domanda è: come si traduce in un'implementazione di livello inferiore? Cosa succede esattamente dietro la scena quando viene soddisfatta una definizione ricorsiva?

+0

Probabilmente è stato chiesto e risposto prima, ma la ricerca di "definizione ricorsiva" riporta solo le domande relative alla ricorsione in senso algoritmico –

+0

[questo] (https://hackhands.com/lazy-evaluation-works-haskell/) potrebbe aiutare. – Alec

+0

Inizia con la comprensione di '[1 ..]'. –

risposta

5

Ecco una semplice funzione ricorsiva che ti dà il numero triangolare n-esimo:

triag 0 = 0 
triag n = n + triag (n-1) 

La soluzione triag' = zipWith (+) [1..] $ 0 : triag' è qualcosa di più di fantasia: E 'corecursive (click, click). Invece di calcolare l'ennesimo numero riducendolo al valore di input più piccoli, si definisce l'intera sequenza infinita di numeri triangolari specificando ricorsivamente il valore successivo, dato un segmento iniziale.

In che modo Haskell gestisce tale corecursion? Quando incontra la tua definizione, nessun calcolo viene effettivamente eseguito, viene posticipato fino a quando i risultati sono necessari per ulteriori calcoli. Quando si accede a un particolare elemento dell'elenco triag', Haskell inizia a calcolare gli elementi dell'elenco in base alla definizione, fino all'elemento a cui si accede. Per ulteriori dettagli, ho trovato utile l'articolo this sulla valutazione lazy. In breve, la valutazione lenta è ottima, a meno che non sia necessario prevedere l'utilizzo della memoria.

Here è una domanda SO simile, con una spiegazione passo passo della valutazione di fibs = 0 : 1 : zipWith (+) fibs (tail fibs), una definizione corecisiva della sequenza di Fibonacci.

+0

Ma dov'è il caso base in la definizione che ho fornito come esempio? Lo prende da 1 da [1 ..] e 0 da 0: tn? –

+1

Supponiamo di accedere al primo elemento di 'triag'': che può essere calcolato direttamente, è' 1 + 0', la somma dei primi elementi di '[1 ..]' e '0: triag''. Ora il secondo: È '2 + 1' dove' 2' è il secondo elemento di '[1 ..]' e '1' il secondo elemento di' 0: triag'', cioè è il primo elemento di 'triag '', 1. In questo modo qualsiasi elemento di' triag'' è definito dalla soluzione e può essere calcolato secondo le necessità. – lodrik

Problemi correlati