2013-05-13 57 views
6

我想用A的某些鏡頭比如創建一個功能A -> Bool謂詞。 ((>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 .==. bar(其中foobar是透鏡)。不幸的是,lens包也定義了自己的(.<)運算符,所以也許其他一些命名約定會更好。這只是我想到的第一個想法。

使用這些新的操作,你就可以寫這樣的東西

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

這是偉大的!我不知道有沒有辦法使用多參數類型類來創建<=工作? – 2013-07-07 02:03:22