2012-02-17 4 views
1

Почему мой шаблон совпадает внутри перекрытия блока?Почему эти совпадения совпадают?

(q, m) <- newRq 
let m2 = appendMsg "first" key m 
    (q4, m4) = case m2 of 
       m -> deleteRec key q m2 
       _ -> (q, m2) 

компилируется с предупреждением

Warning: Pattern match(es) are overlapped 
     In a case alternative: _ -> ... 

и не работает, как я хочу. Это только кажется, что для (q4, m4) всегда возвращает

[], fromList [] 

пренебрегая, что значения m2 и РТО. Есть ли локальные переменные, где я их не ожидаю?

То, что я хочу достичь словами: Если m2 и m равны, то (q4, m4) следует оценить до deleteRec key q m2, в противном случае - (q, m2).

ответ

11

Первый образец в case (m) соответствует всем требованиям и присваивает его m. Второй соответствует всем и отбрасывает его (_), но ему ничего не остается, потому что m получит все.

Я думаю, что вы имели в виду, что этот случай работал как оператор switch, но он фактически работает как набор шаблонов, очень похожий на объявление функции. Таким образом, ваш case такой же, как что-то вроде:

check m2 
    where check m = deleteRec key q m2 
     check _ = (q, m2) 

В этом коде, вы, вероятно, лучше от только с помощью if:

if m == m2 then deleteRec key q m2 else (q, m2) 

Вы также могли бы рассмотреть отступов в if заявление по-разному:

if m == m2 
then deleteRec key q m2 
else (q, m2) 

также должен работать.

Однако, в общем, вы можете использовать охранник в case заявления, так что это будет работать также:

case m2 of 
    val | m2 == m -> deleteRec key q m2 
     | otherwise -> (q, m2) 

Это, очевидно, труднее читать, чем if, но если у вас больше филиалов или необходимость для выполнения фактического сопоставления с образцом это имело бы смысл.

+0

Истина для if, но я просто сидел в течение одного часа, чтобы избежать этого, так как я всегда читал, что это не идиоматично, и что в Haskell разработчики должны использовать шаблон, где это возможно. –

+3

Да, вы * должны * использовать образец соответствия, когда это возможно. Но это невозможно для сопоставления с * значением * переменной. Переменная в шаблоне - это просто «дыра», например '_', которая может взять что угодно; Затем он присваивает все, что было там, для этого имени. –

+0

Есть ли еще альтернатива if-then-else? –

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