класс типов для доступа к определенным полям в записях на основе их типа
Нечто подобное может быть достигнуто с помощью общего программирования , техники для проверки структурытипы данных и определяющие функции, которые работают с различными типами данных в соответствии со структурой каждого.
Чтобы использовать общее программирование, необходимо включить расширение DeriveGeneric
и импортировать GHC.Generics
module.
{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics
type Money = Double
type Name = String
type ErrMsg = String
data SomeRecord = SomeRecord (Either ErrMsg Name) (Either ErrMsg Money) deriving (Generic)
Написание функции «типизированный метод доступа» на основе генериков было бы сложно.К счастью, эта функциональность уже реализована в модуле Data.Generics.Product.Typed
пакета generic-lens .Этот модуль предоставляет объектив typed
, который позволяет нам нацеливать поля в записи по их (уникальному) типу.
(A lens - это значение, которое упаковывается вместегеттер и сеттер для поля записи. Пакет lens содержит основные определения и функции для работы с ними, в частности, функцию view
для получения значения поля.)
import Control.Lens (view)
import Data.Generics.Product.Typed (typed)
moreMoney :: Either ErrMsg Money
moreMoney = fmap (\money -> money + 200.0) $ view typed record
Здесь компилятор определил, что нам нужно поле Money
из-за сигнатуры типа.Но мы могли бы также использовать явное приложение типа :
{-# LANGUAGE TypeApplications #-}
moreMoney' = fmap (\money -> money + 200.0) $ view (typed @(Either _ Money)) record