Spec-Zone.ru › Haskell 9

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

При проектировании встроенных языков доменной специфики на 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.12.1/docs/users_guide/exts/type_errors.html

Spec-Zone.ru

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