2012-07-17 3 views

답변

27

Traversable과 결합하면 유용합니다.

getConst . traverse Const :: (Monoid a, Traversable f) => f a -> a 

이것은 많은 자료를 함께 사용하는 일반적인 방법입니다. ApplicativeMonad에서 분리 할 가치가 있다고 확신하는 사용 사례 중 하나였습니다. 나는 자유 변수의 표현에 의해 매개 변수화 Traversable Term에 대한 검사가 발생 할 일반화 elem

elem :: Eq x => x -> Term x -> Bool 

같은 물건을 필요로했다. 나는 Term의 표현을 계속 변경했으며 효과있는 매핑이 아닌 축적을 수행하는 엄청난 순회 기능을 수정하는 데 지쳐있었습니다. 나는이 둘을 포괄하는 추상화를 발견하게되어 기뻤다.

+0

http://www.soi.city.ac.uk/~ross/papers/Applicative.html 섹션 4는 트래버스 트릭에 대한 좋은 참고 자료입니다. –

+0

'foldMap id'가 제약 조건이 적은 동일한 결과를 생성하지 않습니까? ('Traversable' 대신에'Foldable')? –

+1

실제로 Foldable이 존재합니다. 그러나,'Traversable'은'foldMapDefault'의 위와 같이 모든 것을'Foldable'로하는 것이 유용합니다. Plug : SHE는'DefaultSuperclassInstances'를 지원합니다. 그래서'Traversable'은 모든 것이 자동적 인 디폴트에 의해 Foldable이되도록합니다. – pigworker

6

모든 기능 (Applicative) Functor에 대해 작동하는 기능 또는 데이터 구조가 있고 축약 된 의미로 다시 사용하고자 할 때 유용합니다. 주어진 임의의 함수에서 작동하는 함수에 const 또는 id을 전달하는 것과 유사합니다.

Van Laarhoven lenses 임의 펑의 관점에서 정의되고, (필드 업데이터를 유도하고 Identity 동등 사소한) 필드 접근을 유도하기 Const를 사용한다.

Traversable 유형은 pigworker 언급으로, 이것의 또 다른 예입니다.

7

dave4420에 언급 된 것처럼, Van Laarhoven 렌즈 용 접근 자 및 업데이터를 구현하려면 Const functor가 필요합니다. 정교하게하려면 : 가브리엘 곤잘레스가 지적

{-# 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