С GHC 7.6.1.
При разработке иногда желательно разрешить компиляцию, даже если в коде есть ошибки типов. Рассмотрим следующий случай:
module Main where a :: Int a = 'a' main = print "b"
Даже если a имеет ошибочный тип, оно в конечном итоге не используется, поэтому, если нас интересует только main, может быть полезно проигнорировать проблемы в a.
Для более подробной мотивации и деталей, пожалуйста, обратитесь к странице вики или к оригинальной статье.
6.4.23.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.23.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.23.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