2014-10-16 29 views
8

Genellikle lensler kullanarak değerler alan, değerlere bazı işlevler uygulayıp sonucu döndüren işlevleri yapıyorum. Örneğin, alıcılar birinci sınıf birleştirmek ve (belki tip (b -> c -> d) -> Getter a b -> Getter a c -> Getter a d arasında) başka gaz giderici dönmek için bazı combinator olmalıdır gibi \pair -> (pair ^. _1) + (pair ^. _2)Haskell lens kütüphanesiyle, alıcıları "birinci sınıf" olarak nasıl ele alabilirim?

hissediyorum bir çift unsurlarını toplamak. Herhangi bir yardım?

cevap

2

açıklanmıştır gibi, Getter a b'un tepesi, (a -> b)'a izomorftur. Bu, aynı bilgileri içerdikleri ve irade ile birbirleriyle değiştirilebilecekleri anlamına gelir. Bu bilgi ile

fromGetter :: Getter a b -> (a -> b) 
fromGetter g = view g 

toGetter :: (a -> b) -> Getter a b 
toGetter = to 

istediğiniz işlevi oluşturmak için, J. Abrahamson gösterdiği gibi, (->) için Applicative örneğini kullanabilirsiniz: Biz objektif kütüphane sağlayan işlevleri kullanarak birbirlerine çevirebilirsiniz

myCombinator :: (b -> c -> d) -> Getter a b -> Getter a c -> Getter a d 
myCombinator fn g1 g2 = toGetter (fn <$> fromGetter g1 <*> fromGetter g2) 
+0

ben bunu yapmak zorunda olacağını düşünüyorum. Ayrıca, bu etki alanına işlevleri kaldırmak için <$> ve <*> 'eşdeğerlerini tanımlayabilirim. –

3

Her zaman için Monoid örneği tarafından destekli olabilir, biraz daha az genel (->)

(+) <$> view _1 <*> view _2 :: Num a => (a,a) -> a 

ya, için Applicative örneğini kullanabilirsiniz Getter s

>>> view (_1 <> _2) (Sum 1, Sum 2) 
Sum {getSum = 3}