TLDR; В большинстве случаев вы, вероятно, захотите использовать функцию with
и относительные объективы.
Использование класса типов HasSubSnaplet является совершенно необязательным шаблоном, который может уменьшить шаблон «with subSnaplet» в ситуациях, когда не имеет смысла иметь более одного экземпляра SubSnaplet. Мы решили сделать это для оснастки Heist, которая поставляется в пакете оснастки, потому что это имеет смысл для оснастки Heist и предоставляет пользователям пример шаблона.
Поскольку класс типов является полностью необязательным и приблизительно ортогональным к выбору объектива, в оставшейся части этого ответа я сосредоточусь на том, что делать без класса типов.
Назначение API заключается в том, что вы используете линзы (а не "простые ссылки", которые обертывают вас в тип данных Snaplet) для доступа к вашему состоянию. Это связано с тем, что изменение состояния во время обработки запроса является фундаментальной возможностью, которую мы хотели предоставить Snaplets. По большей части, мы намеревались сделать Snaplet
непрозрачной оболочкой, к которой конечному пользователю не нужно прикасаться, кроме как в типе состояния его Snaplet. Вот почему экземпляр MonadState возвращает вас непосредственно к вашему типу без оболочки Snaplet.
С учетом вышесказанного существует четыре основных шаблона доступа. Мы можем видеть это, глядя на класс MonadSnaplet .
with :: Lens v (Snaplet v') -> m b v' a -> m b v a
withTop :: Lens b (Snaplet v') -> m b v' a -> m b v a
with' :: Lens (Snaplet v) (Snaplet v') -> m b v' a -> m b v a
withTop' :: Lens (Snaplet b) (Snaplet v') -> m b v' a -> m b v a
Шаблон линз, воплощенный в первых двух функциях, - это тип линз, которые генерируются для вас автоматически пакетом data-lens-template с TemplateHaskell и являются наиболее естественными для использования. Поэтому это рекомендуемый шаблон. (Отсюда и более короткое, не загрунтованное имя.) Разница между with
и withTop
заключается в том, что with
использует относительную линзу, а withTop
- абсолютную. Большую часть времени я использую относительные линзы. Но мы хотели разрешить использование абсолютных объективов, потому что я могу представить сложные приложения, в которых один моментал может потребоваться для чего-то, предоставленного другим механизмом, но который не является потомком текущего механизма.
Иногда возникают ситуации, когда вы хотите иметь возможность использовать личный объектив. Это требует Lens (Snaplet a) (Snaplet b)
. Таким образом, вторые две загрунтованные функции аналогичны первым двум, за исключением того, что они используют линзы такого типа.