3 ms·
In practice, Haskell doesn't do this. import System.IO.Unsafe import Prelude hiding (last) last :: [Int] -> Int last (x:[]) = x last (x:xs
by lalaithion 6y ago
In practice, Haskell doesn't do this.
import System.IO.Unsafe
import Prelude hiding (last)
last :: [Int] -> Int
last (x:[]) = x
last (x:xs) = unsafePerformIO (do
print x
return (last xs))
secondToLast :: [Int] -> Int
secondToLast (x:y:[]) = x
secondToLast (x:xs) = unsafePerformIO (do
print x
return (secondToLast xs))
main = let
list = [1,2,3,4,5,6]
x = last list
y = secondToLast list
in print (x + y)
The above code outputs
1
2
3
4
5
1
2
3
4
11
indicating that it traversed the list twice, fully completing one traversal before starting the next.
- Blikkentrekker 6y agoYes, it doesn't do it there on optimization level 2, however it does do it here for instance: import System.IO.Unsafe debug x = unsafePerformIO $ print x >> pure x map1 = map $ debug . (+ 1) map2 = map $ debug . (* 2) main = let list = [1,2,3,4,5,6] newlist = map1 list newerlist = map2 newlist in print newerlist The output of this is: 2 4 3 6 4 8 5 10 6 12 7 14 [4,6,8,10,12,14] Showing that it was smart enough to traverse once. If `map1` and `map2` were imported by some library, it would be close to impossible to speak of maintaining stable a.b.i.'s to both these functions without the compiler somehow being able to turn them inside out and traverse only once.