-
DerivingStrategies -
- Начиная с:
-
8.2.1
- Статус:
-
Включено в
GHC2024
Разрешает использовать несколько
deriving, каждое из которых может быть квалифицировано стратегией.
В большинстве случаев каждое объявление deriving однозначно порождает экземпляр класса типов. Однако существует особый случай, когда одновременное включение расширений GeneralizedNewtypeDeriving и DeriveAnyClass может привести к неоднозначности при выводе. Рассмотрим следующий пример
{-# LANGUAGE DeriveAnyClass, GeneralizedNewtypeDeriving #-}
newtype Foo = MkFoo Bar deriving C
Можно выбрать либо подход DeriveAnyClass для вывода C, либо подход GeneralizedNewtypeDeriving для вывода C; оба варианта будут равноценны. В такой ситуации GHC по умолчанию предпочитает DeriveAnyClass, но это неудовлетворительное решение, поскольку оно не позволяет пользователям использовать оба языковых расширения в одном модуле.
Чтобы сделать это поведение более надёжным, в GHC предусмотрено понятие стратегий вывода, позволяющих пользователю явно указать, какой подход использовать при выводе экземпляра. Чтобы включить эту возможность, необходимо включить языковое расширение DerivingStrategies. Стратегию вывода можно указать в предложении вывода
newtype Foo = MkFoo Bar deriving newtype C
Или в отдельном объявлении вывода
deriving anyclass instance C Foo
DerivingStrategies также позволяет использовать несколько предложений вывода в одном объявлении типа данных, чтобы пользователь мог вывести одни экземпляры с помощью одной стратегии, а другие — с помощью другой. Например:
newtype Baz = Baz Quux deriving (Eq, Ord) deriving stock (Read, Show) deriving newtype (Num, Floating) deriving anyclass C
В настоящее время доступны следующие стратегии вывода:
-
stock: Поручить GHC реализовать «стандартный» экземпляр для типа данных, если это возможно (например,Eq,Ord,Generic,Data,Functorи т. д.) -
anyclass: ИспользоватьDeriveAnyClass(см. Вывод любых других классов) -
-
newtype: UseGeneralizedNewtypeDeriving
-
-
via: ИспользоватьDerivingVia(см. Вывод с помощью)
6.6.7.1. Стратегия вывода по умолчанию
Если стратегия вывода явно не указана, могут применяться несколько стратегий. В таком случае GHC выбирает стратегию следующим образом:
-
Стандартные классы типов, то есть указанные в отчёте и доступные благодаря языковым расширениям, выводятся с помощью стратегии
stock, за исключением следующих случаев:- Для новых типов
Eq,Ord,IxиBoundedвсегда выводятся с помощью стратегииnewtype, даже еслиGeneralizedNewtypeDerivingне включено. (Наблюдаемой разницы с экземплярами, выведенными стандартной стратегией, быть не должно.) - Также для новых типов
Functor,FoldableиEnumвыводятся с помощью стратегииnewtype, если включеноGeneralizedNewtypeDerivingи вывод завершается успешно.
- Для новых типов
-
Для любого другого класса типов:
- Если включено
DeriveAnyClass, используетсяanyclass. - Если включено
GeneralizedNewtypeDerivingи вывод выполняется для нового типа, используетсяnewtype.
Если к предложению вывода применимы оба правила, используется
anyclass, а пользователь получает предупреждение о неоднозначности. Предупреждения можно избежать, явно указав нужную стратегию вывода. - Если включено