Пакет Lens: TH Deriving instance for Тип данных, содержащий производный тип данных - PullRequest
0 голосов
/ 23 мая 2018

У меня есть следующее:

data Dog =
  Dog
  { _x :: Int
  }
makeFieldsNoPrefix ''Dog

data Cat =
  Cat
  { _dog :: Dog
  }
makeFieldsNoPrefix ''Cat

Это дает мне класс HasX и HasDog вместе с экземплярами instance HasDog Cat Dog и instance HasX Dog Int

Но я бытакже нравится генерировать instance HasX Cat Int, эта функция TH доступна где-нибудь?

1 Ответ

0 голосов
/ 24 мая 2018

Есть по крайней мере две веские причины makeFields не генерирует Has экземпляров для транзитивно включенных полей.

  1. В большой структуре, состоящей из множества типов данных, это будет медленно (O(n ^ 2)) для генерации Has экземпляров для каждого поля, которое транзитивно включено где-то в структуре.
  2. Не всегда существует очевидный выбор, который x выбрать.Рассмотрим

    data TwoDogs = { _dog1 :: Dog, _dog2 :: Dog }
    

    Какие Dog _x должны TwoDogs HasX доступ к объективу?Это Lens, а не Traversal, поэтому вы должны выбрать один.Это не разумно ожидать, что автоматизированный инструмент примет это решение за вас.

К счастью, линзы очень легко составить.Если вы хотите, чтобы ваш тип имел экземпляр HasX, который идентифицирует конкретный _x, где-то вложенный в структуру (согласно некоторому правилу для конкретного домена), вы можете просто написать один.

instance HasX Cat Int where x = dog.x
...