Ответ 1
Фактическая информация о проблеме:
Warning: Pattern match(es) are non-exhaustive
In an equation for `fun': Patterns not matched: Inl _
Это правда. Вы предоставляете аргумент конструктора Inr
, но не конструктор Inl
.
На что вы надеетесь, так как нет способа предоставить значение типа Sig B
, которое использует конструктор Inl
(ему понадобится аргумент типа Foo B
, но единственный конструктор для Foo
имеет тип Foo A
), что ghc заметит, что вам не нужно обрабатывать конструктор Inl
.
Проблема в том, что из-за дна каждый тип населен. Существуют значения типа Sig B
, которые используют конструктор Inl
; есть даже не-нижние значения. Они должны содержать дно, но они сами не внизу. Таким образом, программа может оценивать вызов fun
, который не соответствует; о том, о чем предупреждает ghc.
Итак, чтобы исправить это, вам нужно изменить fun
на что-то вроде этого:
fun :: Sig B -> Int
fun (Inr Bar) = 1
fun (Inl foo) = error "whoops"
Но теперь, если вы позже добавите Baz :: Foo B
, эта функция - это бомба замедленного действия, ожидающая своего появления. Это должно быть хорошо для ghc, чтобы предупредить об этом, но единственный способ сделать это - сопоставить шаблон Foo
с текущим набором шаблонов. К сожалению, нет правильных шаблонов, которые вы можете поместить там! Foo
, как известно, имеет тип Foo B
, который обитает только внизу, и вы не можете написать шаблон для дна.
Но вы можете передать его функции, которая принимает аргумент полиморфного типа Foo A
. Эта функция могла бы сопоставляться со всеми существующими в настоящее время конструкторами Foo
, поэтому вы получите предупреждение, если позже их добавить. Что-то вроде этого:
fun :: Sig B -> Int
fun (Inr Bar) = 1
fun (Inl foo) = errorFoo foo
where
errorFoo :: Foo a -> b
errorFoo Foo = error "whoops"
Теперь вы правильно обработали все конструкторы :+:
в fun
, "невозможный" случай просто выдает ошибки, если он когда-либо на самом деле происходит, и если вы когда-либо добавляете Baz :: Foo B
, вы получаете предупреждение о не- исчерпывающий шаблон в errorFoo
, который, по крайней мере, направляет вас на fun
, потому что он определен в прикрепленном where
.
В обратном направлении, когда вы добавляете не связанные конструкторы в Foo
(например, больше типа Foo A
), вам нужно добавить еще несколько случаев в errorFoo
, и это может быть несвоевременным (хотя и легким и механическим), если у вас есть много функций, применяющих этот шаблон.