Начиная с GHC 7.6.1.
Во время разработки иногда желательно разрешить успешную компиляцию, даже если в коде есть ошибки типов. Рассмотрим следующий пример:
module Main where a :: Int a = 'a' main = print "b"
Хотя a имеет неправильный тип, в конечном итоге оно не используется, поэтому, если нас интересует только main, может быть полезно иметь возможность игнорировать проблемы в a.
Дополнительную мотивацию и подробности см. на странице вики или в оригинальной статье.
6.4.24.1. Включение откладывания ошибок типов
Флаг -fdefer-type-errors определяет, откладываются ли ошибки типов до времени выполнения. Ошибки типов по-прежнему будут выдаваться как предупреждения, но не будут препятствовать компиляции. Чтобы подавить эти предупреждения, можно использовать -Wno-deferred-type-errors.
Этот флаг подразумевает флаги -fdefer-typed-holes и -fdefer-out-of-scope-variables, которые включают такое поведение для типизированных дыр и переменных. При желании можно включить -fdefer-type-errors, не включая -fdefer-typed-holes или -fdefer-out-of-scope-variables, явно указав -fno-defer-typed-holes или -fno-defer-out-of-scope-variables в командной строке после флага -fdefer-type-errors.
-
-fdefer-type-errors -
- Начиная с:
-
7.6
- Подразумевает:
Откладывает как можно больше ошибок типов до времени выполнения. Во время компиляции вы получите предупреждение (вместо ошибки). Во время выполнения использование значения, зависящего от ошибки типов, приведёт к ошибке времени выполнения; при этом любые части кода с корректными типами можно выполнять без проблем. См. также
-Wdeferred-type-errors.
-
-fdefer-typed-holes -
- Начиная с:
-
7.10
Откладывает до времени выполнения ошибки типизированных дыр (ошибки, связанные с именами, начинающимися с подчёркивания (например, «_», «_foo», «_bar»)). Ошибки, возникающие из-за типизированных дыр, будут преобразованы в предупреждения. Использование значения, зависящего от типизированной дыры, приводит к ошибке времени выполнения, как и при использовании
-fdefer-type-errors(который подразумевает эту опцию). См. типизированные дыры.Подразумевается флагом
-fdefer-type-errors. См. также-Wtyped-holes.
-
-fdefer-out-of-scope-variables -
- Начиная с:
-
8.0
Откладывает до времени выполнения ошибки, связанные с переменными вне области видимости (ошибки, связанные с именами, не начинающимися с подчёркивания). Такие ошибки будут преобразованы в предупреждения. Использование значения, зависящего от переменной вне области видимости, приводит к ошибке времени выполнения, как и при использовании
-fdefer-type-errors(который подразумевает эту опцию). См. типизированные дыры.Подразумевается флагом
-fdefer-type-errors. См. также-Wdeferred-out-of-scope-variables.
Во время выполнения, когда требуется вычислить терм, содержащий ошибку типов, эта ошибка преобразуется в исключение времени выполнения типа TypeError. Обратите внимание, что во время выполнения ошибки типов откладываются настолько, насколько это возможно, но недопустимые преобразования типов никогда не выполняются, даже если в конечном итоге они привели бы к значению правильного типа. Например, для следующего кода:
x :: Int x = 0 y :: Char y = x z :: Int z = y
вычисление z приведёт к TypeError времени выполнения.
6.4.24.2. Отложенные ошибки типов в GHCi
Флаг -fdefer-type-errors работает и в GHCi, за одним исключением: для «голых» выражений, введённых в приглашении, ошибки типов не откладываются. Например:
Prelude> fst (True, 1 == 'a')
<interactive>:2:12:
No instance for (Num Char) arising from the literal `1'
Possible fix: add an instance declaration for (Num Char)
In the first argument of `(==)', namely `1'
In the expression: 1 == 'a'
In the first argument of `fst', namely `(True, 1 == 'a')'
В противном случае в обычном случае простой ошибки типа, например при вводе reverse True в приглашении, вы получили бы предупреждение, а затем сразу же ошибку типа при вычислении выражения.
Это исключение не распространяется на инструкции, как показывает следующий пример:
Prelude> let x = (True, 1 == 'a')
<interactive>:3:16: Warning:
No instance for (Num Char) arising from the literal `1'
Possible fix: add an instance declaration for (Num Char)
In the first argument of `(==)', namely `1'
In the expression: 1 == 'a'
In the expression: (True, 1 == 'a')
Prelude> fst x
True
6.4.24.3. Ограничения отложенных ошибок типов
Можно отложить следующие ошибки:
- Переменные термов вне области видимости
- Ограничения равенства; например,
ord Trueприводит к неразрешимому ограничению равенстваChar ~ Bool, которое можно отложить. - Ограничения классов типов и неявных параметров
Все остальные ошибки типов сообщаются немедленно, и их нельзя отложить; например, сигнатура типа с некорректным видом, объявление экземпляра, которое не завершается или имеет неверную форму, экземпляр семейства типов, нарушающий объявленные ограничения инъективности, и т. д.
В некоторых случаях отдельные ограничения нельзя отложить. В частности:
-
Ошибки вида в сигнатуре типа или вида, частичной сигнатуре типа или сигнатуре шаблона. Например:
f :: Int Bool -> Char
Эта сигнатура типа содержит ошибку вида, которую нельзя отложить.
- Равенства типов под forall (ср. #14605).
-
Ошибки вида в видимом применении типа. Например:
reverse @Maybe xs
-
Ошибки вида в объявлении
default. Например:default( Double, Int Int )
-
Ошибки, связанные с линейными типами (ср. #20083). Например:
f :: a %1 -> a f _ = ()
-
Недопустимая полиморфность представления. Например:
f :: forall rep (a :: TYPE rep). a -> a f a = a