2013-05-13 6 views
6
Ben Örneğin A'nın bazı lensler kullanarak bir işlev A -> Bool oluşturmak istiyorum

ile esas olarak alınmaktadır. ((>100).(^.foo)) çok daha iyi değil. Lens olmadan, ((>100) . foo) kullanırdım.Construct lensler

lens ile bu tür yüklemelerin oluşturulmasının iyi bir yolu var mı? İdeal olarak, (\a -> a^.foo > 100 && a^.bar < 50) gibi yüklemelere de izin verir.

cevap

4

Sanırım ((>100).(^.foo)) muhtemelen standart operatörleri kullanarak yapabileceğiniz en iyisidir. Eğer lensler için yeni karşılaştırma operatörleri tanımlamak için istekli iseniz, böyle bir şey yapabileceğini:

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 .||. 

operatör seçimler arkasındaki mantık nokta bir lens vardır tarafını ifade ettiği, bu nedenle yazabilirsiniz ya foo .== 5 veya foo .==. bar (foo ve bar objektiflerdir). Ne yazık ki, lens paketi de kendi (.<) operatörünü tanımlar, bu yüzden başka bir adlandırma kuralı daha iyi olabilir. Bu sadece aklıma gelen ilk fikirdi. Bu yeni operatörleri kullanarak

, sen bu harika

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

gibi şeyler yazmak mümkün olacaktır! Çok parametre tipi sınıfları kullanmanın bir yolu var mı? –