Геттер и сеттер, объединенные в первоклассное значение, называются объективом . Для этого существует немало пакетов; наиболее популярными являются data-lens и fclabels. Это previous SO question - хорошее введение.
Обе из этих библиотек поддерживают получение линз из определений записей с использованием шаблона Haskell (с объективом данных, он предоставляется как an additional package для переносимости). Ваш пример будет выражаться в виде (с использованием синтаксиса данных объектива):
setL idxF_s (b ^. idL_s) a
(или что то же самое: idxF_s ^= (b ^. idL_s) $ a
)
Вы можете, конечно, преобразование линзы в общем виде путем преобразования их геттер и сеттер вместе :
-- I don't know what swap_by_sign is supposed to do.
negateLens :: (Num b) => Lens a b -> Lens a b
negateLens l = lens get set
where
get = negate . getL l
set = setL l . negate
(или, что эквивалентно: negateLens l = iso negate negate . l
)
В родов l, я бы рекомендовал использовать линзы всякий раз, когда вам приходится иметь дело с любым видом нетривиальной обработки записей; они не только упрощают чистое преобразование записей, но и оба пакета содержат удобные функции для доступа и изменения состояния государственной монады с использованием объективов, что невероятно полезно. (Для данных хрусталика, вы хотите использовать data-lens-fd пакет, чтобы использовать эти функции, удобство в любом MonadState
, опять же, они находятся в отдельном пакете для портативности.)
При использовании любого пакет, вы должны начать свои модули с:
import Prelude hiding (id, (.))
import Control.Category
Это потому, что они используют обобщенные формы id
и (.)
функций прелюдии в - id
могут быть использованы в качестве объектива от любого значения к себе (не все, что полезно, по общему признанию,), и (.)
используется для создания линз (например, getL (fieldA . fieldB) a
- то же, что и getL fieldA . getL fieldB $ a
). Более короткое определение negateLens
использует это.
Указатель на операторы-члены не C, а C++. Retagged. –