Spec-Zone.ru › Haskell 9

6.4.23. Пользовательские ошибки времени компиляции

При разработке встроенных предметно-ориентированных языков в Haskell полезно иметь что-то вроде error на уровне типов. Таким образом, разработчик EDSL может показать ошибку типа, специфичную для DSL, вместо стандартной ошибки типов GHC.

Например, рассмотрим класс типов, который не предназначен для использования с функциями, но пользователь случайно применил его к типу функции, возможно, потому что пропустил аргумент функции. Тогда вместо стандартного сообщения GHC об отсутствующем экземпляре было бы лучше вывести более понятное сообщение, специфичное для EDSL. Аналогично, сведение функции уровня типов может остановиться из-за ошибки; в этом случае было бы полезно сообщить об ошибке, специфичной для EDSL, а не о неопределённом типе в общем виде.

Для решения этой задачи GHC предоставляет единственную функцию уровня типов:

type family TypeError (msg :: ErrorMessage) :: k

а также небольшой язык уровня типов (с помощью DataKinds) для создания красиво отформатированных сообщений об ошибках:

-- ErrorMessage is intended to be used as a kind
data ErrorMessage =
      Text Symbol                        -- Show this text as is
    | forall t. ShowType t               -- Pretty print a type
    | ErrorMessage :<>: ErrorMessage     -- Put two chunks of error message next to each other
    | ErrorMessage :$$: ErrorMessage     -- Put two chunks of error message above each other

в модуле GHC.TypeLits.

Например, этот интерфейс можно использовать, чтобы выводить более полезное сообщение об ошибке при применении show к ненасыщенным функциям, например:

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}

import GHC.TypeLits

instance TypeError (Text "Cannot 'Show' functions." :$$:
                    Text "Perhaps there is a missing argument?")
         => Show (a -> b) where
   showsPrec = error "unreachable"

main = print negate

В результате будет выведена следующая ошибка времени компиляции:

Test.hs:12:8: error:
    • Cannot 'Show' functions.
      Perhaps there is a missing argument?
    • In the expression: print negate
      In an equation for ‘main’: main = print negate

© 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/type_errors.html

Spec-Zone.ru

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