2012-07-17 16 views

答えて

27

Traversableと組み合わせて使うとかなり役に立ちます。

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

これは、たくさんのものを一緒に輝かせるための一般的なレシピです。 ApplicativeMonadから分離する価値があることを私に納得させたのはユースケースの1つでした。私は自由変数の表現によってパラメータTraversable Termのためのチェックを行うために発生する一般的なelem

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

ようなものを必要としていました。私はTermの表現を変更し続けました。そして、効果的なマッピングではなく、いくつかが累積を行っていた膨大なトラバース関数を修正するのに疲れました。私は両方をカバーする抽象概念を見つけるのはうれしいです。

+0

http://www.soi.city.ac.uk/~ross/papers/Applicative.htmlセクション4は、トラバーストリックの良い参考資料です。 –

+0

foldingMap idは少ない制約で同じ結果を生成しません( 'Traversable'の代わりに' Foldable')? –

+1

実際には、それは 'Foldable'が存在する理由です。しかし、 'Traversable'はすべて' Foldable'であることが、 'foldMapDefault'の構築であるという点で、むしろ有益です。プラグイン:SHEは 'DefaultSuperclassInstances'をサポートしています。そのため、Traversableはすべてデフォルトで' Foldable'になっています。 – pigworker

6

すべて(ApplicativeFunctorで機能する関数またはデータ構造を持ち、縮退した意味で再利用したい場合に便利です。与えられた関数で動作する関数にconstまたはidを渡すのと似ています。

Van Laarhoven lenses任意ファンクタに関して定義され、そして(フィールドアップデータを導出し、Identity等しく些細)フィールドアクセサを導出するConstを使用しています。

Traversableタイプは、これとは別の例です。

7

dave4420に記載されているように、Van Laarhovenレンズのアクセッサとアップデータを実装するには、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 
関連する問題