2013-11-17 5 views
6

Недавно я столкнулся с ошибкой при использовании threepenny-gui, и это было решено путем изменения кода из совпадения шаблонов в обозначении <-, чтобы сопоставить образец с обозначением let.Соответствие шаблону в примечаниях к примечанию vs 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

Дополнительная плата Детали TFORM: ОС: 10.8.5 GHC: 7.6.3

редактировать: добавить тот факт, что это происходит в IO монада

ответ

9

На самом деле, да, они производят различные виды ошибок. Отсутствует спичкой узор в let связывание вызывает шаблон матч error всякий раз, когда матч оцененную пока отсутствует совпадение шаблона из (<-) просто вызывает fail функция Monad экземпляра

В качестве простого примера рассмотрим 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.

+0

Это очень хороший вопрос и отвечает на вопрос как отправлено. Это подразумевает, что существует некоторая разница в строгости, которая заставляет ошибку запускаться в обозначении do, но не с обозначением let в этом случае. Соответствие шаблону в монаде IO заставляет шаблон шаблона совпадать, а let - ленивый и позволяет ему оценивать позже, если потребуется? – Davorak

+2

'let' может определенно быть более ленивым, как с чем-то вроде' do {let Just x = Just(); return x} 'равнозначно' return (пусть Just x = Just() в x) ', в то время как то же самое с привязкой шаблона привязки все равно должно дать монаде шанс выполнить привязку. –

+2

Эта странная небольшая разница в семантике на самом деле является цельной причиной, почему «Monad' имеет функцию« fail », поскольку она появилась до того, как« MonadPlus »сделал. Существуют также различные предложения, которые имеют шаблон «Monad», соответствующий либо desugar, либо 'let' binding, либо действительный только для экземпляров« MonadPlus ». –