2013-05-13 11 views
6

と述語を構築し、私は、例えばAの一部のレンズを使用して機能A -> Boolを作成したい:レンズ

data A = A { _foo :: Int, _bar :: Int } 
makeLenses ''A 

l :: [A] 

l' = filter (\a -> a^.foo > 100) l 

フィルタ述語は、ビットclumpsyを探します。 ((>100).(^.foo))はあまり良くありません。レンズがなければ、((>100) . foo)を使用します。

lensでそのような述部を作成する良い方法はありますか?理想的には、(\a -> a^.foo > 100 && a^.bar < 50)のような述語も許可します。

答えて

4

私は((>100).(^.foo))は、おそらく標準の演算子を使用することでできると思います。あなたは、レンズのための新しい比較演算子を定義するために喜んでいる場合は、あなたのような何かができる:

import Control.Lens hiding ((.>)) 
import Control.Monad  (liftM2) 
import Control.Monad.Reader (MonadReader) 
import Data.Function  (on) 

(.==) :: (MonadReader s m, Eq a) => Getting Bool s a -> a -> m Bool 
(.==) l = views l . (==) 
infix 4 .== 

(.==.) :: (MonadReader s m, Eq a) => Getting a s a -> Getting a s a -> m Bool 
(.==.) = liftM2 (==) `on` view 
infix 4 .==. 

(.<) :: (MonadReader s m, Ord a) => Getting Bool s a -> a -> m Bool 
(.<) l = views l . flip (<) 
infix 4 .< 

(.<.) :: (MonadReader s m, Ord a) => Getting a s a -> Getting a s a -> m Bool 
(.<.) = liftM2 (<) `on` view 
infix 4 .<. 

(.<=) :: (MonadReader s m, Ord a) => Getting Bool s a -> a -> m Bool 
(.<=) l = views l . flip (<=) 
infix 4 .<= 

(.<=.) :: (MonadReader s m, Ord a) => Getting a s a -> Getting a s a -> m Bool 
(.<=.) = liftM2 (<=) `on` view 
infix 4 .<=. 


(.>) :: (MonadReader s m, Ord a) => Getting Bool s a -> a -> m Bool 
(.>) l = views l . flip (>) 
infix 4 .> 

(.>.) :: (MonadReader s m, Ord a) => Getting a s a -> Getting a s a -> m Bool 
(.>.) = liftM2 (>) `on` view 
infix 4 .>. 

(.>=) :: (MonadReader s m, Ord a) => Getting Bool s a -> a -> m Bool 
(.>=) l = views l . flip (>=) 
infix 4 .>= 

(.>=.) :: (MonadReader s m, Ord a) => Getting a s a -> Getting a s a -> m Bool 
(.>=.) = liftM2 (>=) `on` view 
infix 4 .>=. 

(.&&.) :: Monad m => m Bool -> m Bool -> m Bool 
(.&&.) = liftM2 (&&) 
infix 3 .&&. 

(.||.) :: Monad m => m Bool -> m Bool -> m Bool 
(.||.) = liftM2 (||) 
infix 3 .||. 

オペレータの選択の背後にあるロジックは、ドットがレンズを持っている側を意味していることですので、あなたが書くことができるのいずれかfoo .== 5foo .==. barfooおよびbarはレンズです)。残念ながら、lensパッケージでは独自の(.<)演算子も定義されています。これはちょうど私の心に来た最初のアイデアでした。これらの新しい演算子を使用して

、あなたはこれが素晴らしいです

l' = filter (foo .> 100 .&&. bar .< 50) l 
+0

ようなものを書くことができるでしょう!私は多分、多項式型のクラスを使ってちょうど<>仕事をすることがあるのだろうか? –

関連する問題