Подтвердить что ты не робот

Как объединить линзы (не сочинять)

В haskell без объективов я могу делать такие вещи, как:

data Item = Item { quantity :: Double, price ::Double }

cost :: Item -> Double
cost = (*) <$> quantity <*> price

Если я использую объективы вместо этого, как я могу сделать эквивалент? Лучшее, что я могу сделать, это

cost = to $ (*) <$> (^. quantity) <*> (^. price)

Есть ли лучший способ? (конечно, я хочу a getter или эквивалент)

4b9b3361

Ответ 1

Мне просто пришло в голову, что вам не нужен специальный синтаксис для объединения объективов. Если вы создаете объективы с использованием шаблона Haskell (что вы должны делать), то у вас уже есть примитивные геттеры для каждого поля, которому предшествует символ подчеркивания.

Следовательно, вы можете использовать примитивные геттеры для создания тэга phantom cost следующим образом:

{-# LANGUAGE TemplateHaskell #-}

import Control.Lens

data Item = Item { _quantity :: Double
                 , _price    :: Double
                 }

$(makeLenses ''Item)

cost :: Getter Item Double
cost = to $ (*) <$> _quantity <*> _price

item :: Item
item = Item { _quantity = 2, _price = 5.0 }

main :: IO ()
main = print $ view cost item

Однако, если у вас нет доступа к примитивным геттерам, вы можете определить cost как:

cost :: Getter Item Double
cost = to $ (*) <$> view quantity <*> view price

Ваши пальцы не должны перемещаться слишком далеко от домашней строки, чтобы напечатать view.