Сопоставление с образцом в нотации 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,

Другие вопросы по тегам