52700.fb2
= inRange (bounds arr) i && arr ! i < arr ! (x, y)
В функции разметки мы воспользуемся ассоциативным массивом из модуля Data.Map. Функция nub из
модуля Data.List убирает из списка повторяющиеся элементы. Затем мы составляем список пар из коорди-
нат водостоков и меток и в самом конце размечаем исходный массив:
label :: SinkMap -> LabelMap
label a = fmap (m M.! ) a
where m = M. fromList $ flip zip [’a’ .. ] $ nub $ elems a
11.4 Ленивее некуда
Мы выяснили, что значение может редуцироваться только при сопоставлении с образцом и в специальной
функции seq. Функцию seq мы можем применять, а можем и не применять. Но кажется, что в декомпозиции
мы не можем уйти от необходимости проведения хотя бы одной редукции. Оказывается можем, в Haskell для
этого предусмотрены специальные ленивые образцы (lazy patterns). Они обозначаются знаком тильда:
lazyHead :: [a] -> a
lazyHead ~(x:xs) = x
Перед скобками сопоставления с образцом пишется символ тильда. Этим мы говорим вычислителю: до-
верься мне, здесь точно такой образец, можешь даже не проверять дальше. Он и правда дальше не пойдёт.
Например если мы напишем такое определение:
lazySafeHead :: [a] -> Maybe a
lazySafeHead ~(x:xs) = Just x
lazySafeHead []
= Nothing
Если мы подставим в эту функцию пустой список мы получим ошибку времени выполнения, вычислитель
доверился нам в первом уравнении, а мы его обманули. Сохраним в модуле Strict и проверим:
Prelude Strict> :! ghc --make Strict
[1 of 1] Compiling Strict
( Strict. hs, Strict. o )
Strict. hs:67:0:
Warning: Pattern match(es) are overlapped
In the definition of ‘lazySafeHead’: lazySafeHead [] = ...
Prelude Strict> :l Strict
Ok, modules loaded: Strict.
Prelude Strict> lazySafeHead [1,2,3]
Just 1
Prelude Strict> lazySafeHead []
Just *** Exception: Strict. hs:(67,0)-(68,29): Irrefutable
pattern failed for pattern (x : xs)
При компиляции нам даже сообщили о том, что образцы в декомпозиции пересекаются. Но мы были
упрямы и напоролись на ошибку, если мы поменяем образцы местами, то всё пройдёт гладко:
Prelude Strict> :! ghc --make Strict
[1 of 1] Compiling Strict
( Strict. hs, Strict. o )
Prelude Strict> :l Strict
Ok, modules loaded: Strict.
Prelude Strict> lazySafeHead []
Nothing
188 | Глава 11: Ленивые чудеса
Отметим, что сопоставление с образцом в let и where выражениях является ленивым. Функцию lazyHead
мы могли бы написать и так:
lazyHead a = x