In Haskell, potrei implementare if
come questo:Idris valutazione eager
if' True x y = x
if' False x y = y
spin 0 =()
spin n = spin (n - 1)
Questo si comporta come mi aspetto:
haskell> if' True (spin 1000000)() -- takes a moment
haskell> if' False (spin 1000000)() -- immediate
In Racket, ho potuto implementare un if
2 imperfetto in questo modo:
(define (if2 cond x y) (if cond x y))
(define (spin n) (if (= n 0) (void) (spin (- n 1))))
Questo si comporta come mi aspetto:
racket> (if2 #t (spin 100000000) (void)) -- takes a moment
racket> (if2 #f (spin 100000000) (void)) -- takes a moment
In Idris, potrei implementare if
come questo:
if' : Bool -> a -> a -> a
if' True x y = x
if' False x y = y
spin : Nat ->()
spin Z =()
spin (S n) = spin n
Questo surpris comportamento Mi es:
idris> if' True (spin 1000)() -- takes a moment
idris> if' False (spin 1000)() -- immediate
mi aspettavo Irdis a comportarsi come Racket, dove entrambi gli argomenti sono valutati. Ma non è questo il caso!
Come decide Idris quando valutare le cose?
Grazie! Ho dovuto cambiare 'spin: Nat ->()' per 'spin: Nat -> Bool' (immagino che Idris abbia realizzato'() 'ha solo un abitante e ottimizzato la chiamata a' spin'), ma dopo che l'eseguibile si è preso un momento per correre indipendentemente da quale ramo del "se" è andato giù. – Snowball
Sì, avrebbe cancellato il(). In realtà nel master corrente esegue un'analisi di cancellazione molto più profonda quindi probabilmente dovresti fare qualcosa come stampare il risultato di spin n per essere sicuro che sia stato valutato ... –
Come mai, se è noto che 'spin 1000' è terminando e senza effetti collaterali, questa espressione non viene valutata in fase di compilazione e sostituita dal suo risultato nel codice generato, in modo che entrambe le versioni della riga 'if'' restituiscano immediatamente i loro risultati in fase di esecuzione? (Il commento di palle di neve sopra indica che non è così.) – Lii