2016-09-11 8 views
12

Я смотрел на какой-то источник Haskell код и наткнулся на матч модели с !_, код здесь: http://hackage.haskell.org/package/base-4.9.0.0/docs/src/GHC.List.html#unsafeTakeКогда полезно использовать «строгий шаблон» в Haskell и что он делает?

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 

Я не очень понимаю, как «строгий подстановочные» работает и почему это полезно эта функция (или любая другая функция).

ответ

12

Идея заключается в том, что unsafeTaketake по этому вопросу), когда попросили вернуть первые m элементов пустого списка, он должен вернуть пустой список, независимо от того, что значение m есть. Но что, если m является выражением, которое генерирует исключение? Например, было бы странно, если бы unsafeTake undefined [] вернул []. Поэтому мы должны убедиться, что m оценивает целое число, даже если нам все равно, что его точное значение (для случая с пустым списком, конечно). Это делает unsafeTake так же, как и в первом аргументе, неважно, пуст ли второй аргумент (список) или нет.

+1

Я полагаю, что стоит упомянуть, что если вы используете 'take' функцию с' undefined' как 'n', то вряд ли поймать ошибку в' unsafeTake', потому что 'n' сравнивается с нолем раньше, т.е. оцениваться ранее. Но поскольку предполагается, что функция 'take' должна быть как можно более встроена (как отмечает комментарий), тогда эта проверка может исчезнуть после некоторых оптимизаций. Вот почему нам нужно '! _' в' unsafeTake'. – Shersh

 Смежные вопросы

  • Нет связанных вопросов^_^