When is it useful to use "strict wildcard" in Haskell, and what does it do?
Asked Answered
S

1

12

I was looking at some Haskell source code and came across a pattern match with !_, the code is here: http://hackage.haskell.org/package/base-4.9.0.0/docs/src/GHC.List.html#unsafeTake

take n xs | 0 < n     = unsafeTake n xs
          | otherwise = []

-- A version of take that takes the whole list if it's given an argument less
-- than 1.
{-# NOINLINE [1] unsafeTake #-}
unsafeTake :: Int -> [a] -> [a]
unsafeTake !_  []     = []
unsafeTake 1   (x: _) = [x]
unsafeTake m   (x:xs) = x : unsafeTake (m - 1) xs

I don't really understand how the "strict wildcard" works and why it's useful for this function (or any other function).

Sinaloa answered 11/9, 2016 at 16:21 Comment(0)
I
12

The idea is that unsafeTake (and take for that matter), when asked to return the first m elements of the empty list, it should return the empty list, no matter what the value of m is. But what if m is an expression that throws an exception? For example, it would be weird for unsafeTake undefined [] to return []. So we need to ensure that m evaluates to integer even if we don't care what is its exact value (for the empty list case of course). This makes unsafeTake behave the same way when it comes to its first argument, not matter whether the second argument (the list) is empty or not.

Interleaf answered 11/9, 2016 at 16:25 Comment(1)
I suppose it worth mentioning that if you use take function with undefined as n argument then it is unlikely to catch error in unsafeTake function because n is compared with zero earlier, i.e. it would be evaluated earlier. But because take function is supposed to be inlined as much as possible (as comment says) then this check may disappear after some optimizations. That's why we need !_ in unsafeTake as well.Augustus

© 2022 - 2024 — McMap. All rights reserved.