Почему конструкторы GADT/экзистенциальных данных не могут использоваться в ленивых шаблонах?

сегодня я получил ошибку компилятора при попытке использовать ленивый шаблон при сопоставлении с экзистенциальным конструктором GADT:

конструктор данных existential или GADT нельзя использовать внутри ленивого ( ~ ) шаблона

Почему это ограничение? Что плохого может случиться, если это допустить?

2 ответов


считают

data EQ a b where
  Refl :: EQ a a

если бы мы могли определить

transport :: Eq a b -> a -> b
transport ~Refl a = a

тогда мы могли бы

transport undefined :: a -> b

и таким образом приобрести

transport undefined True = True :: Int -> Int

и затем сбой, а не более изящный провал, который вы получаете при попытке головы-нормализовать undefined.

данные GADT представляют доказательства о типы, поэтому фиктивные данные GADT угрожают безопасности типа. Необходимо быть строгим с ними, чтобы подтвердить эти доказательства: вы не можете доверять недооцененные вычисления при наличии дна.


с "нормальными" данными вы можете пропустить проверку конструктора во время сопоставления шаблонов, при том понимании, что при попытке использовать данные из шаблона он может оказаться несуществующим, тем самым бросая на вас исключение.

с GADT,подпись типа потенциально изменяется в зависимости от того, какой конструктор присутствует. Нам нужно знать о типах в времени компиляции; нет смысла не проверять конструктор, пока вам не понадобятся значения. Если вы do, у вас может быть ошибка несоответствия типа. И это, потенциально, означает сбой вашей программы с ошибкой сегментации (или хуже). Программы Haskell должны никогда обработка выхода онлайн / оффлайн.