Сопоставление с образцом в нотации do и let
Недавно я столкнулся с ошибкой при использовании threepenny-gui, и она была решена путем изменения кода из сопоставления с образцом в нотации do с <-
для сопоставления с шаблоном let.
Есть ли причины, по которым мне следует ожидать изменения в поведении при изменении этих двух форм сопоставления с образцом?
В частности, следующий код:
В монаде IO:
Just events <- Map.lookup elid <$> readMVar sElementEvents
был изменен на:
mevents <- Map.lookup elid <$> readMVar sElementEvents
let Just events = mevents
Вот ссылка на коммит исправленной проблемы для меня: https://github.com/Davorak/threepenny-gui/commit/fbf6cbe25875fafdc64f7a111ddebf485b45143b
Дополнительные сведения о платформе: os: 10.8.5 ghc: 7.6.3
редактировать: добавлен тот факт, что это происходит моно ввода-вывода
1 ответ
На самом деле, да, они производят разные виды ошибок. Отсутствует сопоставление с образцом в let
привязка вызывает совпадение error
всякий раз, когда это совпадение оценивается при отсутствии совпадения шаблона из (<-)
просто вызывает Monad
экземпляра fail
функция
В качестве простого примера рассмотрим Maybe
монада где
instance Monad Maybe where
...
fail _ = Nothing
test1 :: Maybe (Maybe ())
test1 = do
Just a <- return Nothing
return a
test2 :: Maybe (Maybe ())
test2 = do
ma <- return Nothing
let Just a = ma
return a
Если мы называем их обоих, мы получаем совершенно разное поведение
> test1
Nothing
> test2
Just *** Exception: PM.hs:23:7-17:
Irrefutable pattern failed for pattern Data.Maybe.Just a
Обычно неопровержимое сопоставление - плохая идея, если вы не уверены, что невозможно получить отсутствующие шаблоны, но если вы должны сделать это в Monad
тогда иногда неопровержимое сопоставление на привязке лучше, чем в let
,