-
DerivingStrategies -
- Since:
-
8.2.1
- Status:
-
Включено в
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, и пользователю выдаётся предупреждение об неоднозначности. Предупреждение можно избежать, явно указав желаемую стратегию вывода. - При включении