In Haskell, I might implement if
like this:
if' True x y = x
if' False x y = y
spin 0 = ()
spin n = spin (n - 1)
This behaves how I expect:
haskell> if' True (spin 1000000) () -- takes a moment
haskell> if' False (spin 1000000) () -- immediate
In Racket, I could implement a flawed if
like this:
(define (if2 cond x y) (if cond x y))
(define (spin n) (if (= n 0) (void) (spin (- n 1))))
This behaves how I expect:
racket> (if2 #t (spin 100000000) (void)) -- takes a moment
racket> (if2 #f (spin 100000000) (void)) -- takes a moment
In Idris, I might implement if
like this:
if' : Bool -> a -> a -> a
if' True x y = x
if' False x y = y
spin : Nat -> ()
spin Z = ()
spin (S n) = spin n
This behavior surprises me:
idris> if' True (spin 1000) () -- takes a moment
idris> if' False (spin 1000) () -- immediate
I expected Irdis to behave like Racket, where both arguments are evaluated. But that's not the case!
How does Idris decide when to evaluate things?
spin : Nat -> ()
tospin : Nat -> Bool
(I'm guessing Idris realized()
only has one inhabitant and optimized away the call tospin
), but after that the executable took a moment to run regardless of which branch of theif'
it went down. – Piassava