Я только что нашел Const
в документации Control.Applicative
, но мне сложно найти, где это полезно, просто используя Monoid
напрямую.
Что мне не хватает?
Я только что нашел Const
в документации Control.Applicative
, но мне сложно найти, где это полезно, просто используя Monoid
напрямую.
Что мне не хватает?
Это довольно полезно в сочетании с Traversable
.
getConst . traverse Const :: (Monoid a, Traversable f) => f a -> a
Это общий рецепт для совместной работы с кучей вещей. Это был один из прецедентов, которые убедили меня, что стоит отделить Applicative
от Monad
. Мне нужны такие вещи, как обобщенные elem
elem :: Eq x => x -> Term x -> Bool
выполнить проверку наличия для Traversable Term
, параметризованного представлением свободных переменных. Я продолжал изменять представление Term
, и мне надоело модифицировать функции обхода движения, некоторые из которых делали скопления, а не эффектное отображение. Я был рад найти абстракцию, которая охватывала оба.
Как упоминает dave4420, реализация аксессуаров и обновителя для линз Ван Лаарховена включает в себя функтор Const
. Разработать:
{-# LANGUAGE Rank2Types #-}
import Control.Applicative
import Control.Monad.Identity
-- The definition of Van Laarhoven lenses:
type Lens a b = forall f . Functor f => (b -> f b) -> (a -> f a)
-- Getter passes the Const functor to the lens:
get :: Lens a b -> a -> b
get l = getConst . (l Const)
-- Updater passes the Identity functor to the lens:
modify :: Lens a b -> (b -> b) -> (a -> a)
modify l f = runIdentity . l (Identity . f)
set :: Lens a b -> b -> (a -> a)
set l r = modify l (const r)
-- Example: -------------------------------------------
data Person = Person { _name :: String, _age :: Int }
deriving Show
name :: Lens Person String
name f (Person n a) = fmap (\x -> Person x a) (f n)
age :: Lens Person Int
age f (Person n a) = fmap (\x -> Person n x) (f a)
main :: IO ()
main = do
let john = Person "John" 34
print $ get age john
print $ set name "Pete" john
Это полезно, когда у вас есть функция или структура данных, которая работает для всех (Applicative
) Functor
s, и хочет повторно использовать ее в вырожденном смысле. Он аналогичен передаче в const
или id
функциям, выполняющим заданные произвольные функции.
Объективы Ван Лаарховена определяются в терминах произвольных Функторов и используют const
для получения доступа к полю (а также тривиальный Identity
для вывода поля обновления).
Traversable
типы, как упоминает питомник, являются еще одним примером этого.
Как отмечает Габриэль Гонсалес, Const используется для предоставления Getters объективам. http://hackage.haskell.org/package/lens-tutorial-1.0.0/docs/Control-Lens-Tutorial.html. Там вы используете только то, что Const является функтором.
Для обходов вам нужно полное аппликативное поведение, и это становится тем, что описанный питомник в другом ответе.