実験したら、やっぱり評価に必要な部分しかソートされなかったよ
実験は takeWhile じゃなく take でやった

[実験コード]
ucomp :: IORef Int -> Int -> Int -> Ordering
ucomp ref x y = unsafePerformIO $ do
modifyIORef ref (+1)
return $ compare x y

main = do
let g = mkStdGen 1
let xs = shuffle' [1..8] 8 g
rc <- newIORef 0
let ys = take 8 $ sortBy (ucomp rc) xs
putStrLn $ show $ maximum ys
c <- readIORef rc
putStrLn $ show c

take で取り出す要素数を8個と3個で実験し、show c の結果を比較
  8個 c=19
3個 c=14

やっぱ遅延評価ってイイね
ベスト3を決めるのに他言語みたいに全部を評価する必要がない

ちなみに、100万個の要素でもやってみた
  all c=19237801
  3個 c=1413225

質問したけど、ひとりで納得してしまった、すまん