Spec-Zone.ru › Haskell 9

6.6.3. Объявления вывода для самостоятельного использования

StandaloneDeriving
Since:

6.8.1

Status:

Включено в GHC2024, GHC2021

Разрешить использование объявлений вывода deriving для самостоятельного использования.

GHC позволяет использовать объявления вывода deriving для самостоятельного использования, включенные с помощью StandaloneDeriving:

data Foo a = Bar a | Baz String

deriving instance Eq a => Eq (Foo a)

Синтаксис идентичен синтаксису обычного объявления экземпляра за исключением (a) ключевого слова deriving, и (b) отсутствия части where.

Однако, самостоятельный вывод отличается от deriving в ряде важных аспектов:

  • Объявление вывода для самостоятельного использования не обязательно должно находиться в том же модуле, что и объявление типа данных. (Но будьте осторожны с опасностями «сиротских» экземпляров (Модули-сироты и объявления экземпляров).
  • В большинстве случаев вам необходимо предоставить явный контекст (в примере контекстом является (Eq a)), точно так же, как и в обычном объявлении экземпляра. (В отличие от deriving в объявлении типа данных, контекст выводится автоматически.)

    Исключение из этого правила состоит в том, что контекст объявления вывода для самостоятельного использования может выводить свой контекст при использовании единственного дополнительного ограничения диких карт в качестве контекста, например:

    deriving instance _ => Eq (Foo a)
    

    Это по существу то же самое, что если вы написали deriving Eq после объявления data Foo a. Для использования этой функции необходимо использовать PartialTypeSignatures (Частичные типы сигнатур).

  • В отличие от объявления вывода deriving , прикрепленного к объявлению data , экземпляр может быть более специфичным, чем тип данных (предполагая, что вы также используете FlexibleInstances, Правила завершения экземпляров). Рассмотрим, например,

    data Foo a = Bar a | Baz String
    
    deriving instance Eq a => Eq (Foo [a])
    deriving instance Eq a => Eq (Foo (Maybe a))
    

    Это сгенерирует выведенный экземпляр для (Foo [a]) и (Foo (Maybe a)), но другие типы, такие как (Foo (Int,Bool)) , не будут экземпляром Eq.

  • В отличие от объявления вывода deriving , прикрепленного к объявлению data , GHC не ограничивает форму типа данных. Вместо этого GHC просто генерирует соответствующий шаблонный код для указанного класса и выполняет проверку типов. Если произойдет ошибка типа, это ваша проблема. (GHC покажет вам проблемный код, если в нём есть ошибка типа.)

    Достоинства этого подхода заключаются в том, что вы можете выводить экземпляры для GADTs и других экзотических типов данных, при условии, что шаблонный код действительно проходит проверку типов. Например:

    data T a where
       T1 :: T Int
       T2 :: T Bool
    
    deriving instance Show (T a)
    

    В этом примере вы не можете сказать ... deriving( Show ) в объявлении типа данных для T, потому что T является GADTem, но вы можете сгенерировать объявление экземпляра с помощью самостоятельного вывода.

    Недостатки заключаются в том, что если шаблонный код не пройдет проверку типов, вы получите сообщение об ошибке по этому коду, который вы не написали. В то время как с deriving условия ограничения неизбежно более консервативны, но любое сообщение об ошибке может быть более понятным.

  • В большинстве случаев вы не можете использовать самостоятельный вывод для создания экземпляра типа данных, конструкторы которого не находятся в области видимости. Это связано с тем, что выведенный экземпляр сгенерирует код, который использует конструкторы за кулисами, что нарушит абстракцию.

    Исключение из этого правила – DeriveAnyClass, поскольку вывод экземпляра с помощью DeriveAnyClass просто генерирует пустое объявление экземпляра, которое не требует использования конструкторов. Более подробная информация представлена в разделе «Вывод для любых классов».

В других отношениях самостоятельный вывод подчиняется тем же правилам, что и обычный вывод:

  • Объявление deriving instance должно подчиняться тем же правилам относительно формы и завершения, что и обычные объявления экземпляров, управляемые теми же флагами; см. Объявления и разрешение экземпляров.
  • Синтаксис для самостоятельного использования обобщен для новых типов точно так же, как обобщаются обычные deriving ( Обобщенные выведенные экземпляры для новых типов). Например:

    newtype Foo a = MkFoo (State Int a)
    
    deriving instance MonadState Int Foo
    

    GHC всегда обрабатывает последний параметр экземпляра (Foo в этом примере) как тип, для которого выводится экземпляр.

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

Spec-Zone.ru

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