Почему конструкторы 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 должны никогда обработка выхода онлайн / оффлайн.