Spec-Zone.ru › Haskell 9

6.4.24. Откладывание ошибок типов до времени выполнения

Начиная с 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

Подразумевает:

-fdefer-typed-holes, -fdefer-out-of-scope-variables

Откладывает как можно больше ошибок типов до времени выполнения. Во время компиляции вы получите предупреждение (вместо ошибки). Во время выполнения использование значения, зависящего от ошибки типов, приведёт к ошибке времени выполнения; при этом любые части кода с корректными типами можно выполнять без проблем. См. также -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
    

© 2002–2007 The University Court of the University of Glasgow. All rights reserved.
Licensed under the Glasgow Haskell Compiler License.
https://downloads.haskell.org/~ghc/9.14.1/docs/users_guide/exts/defer_type_errors.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API