2013-06-11 7 views
5

Prosty przykład:Używając Lens, jak skomponować setter z inną funkcją g tak, że wyjście g jest nową wartością do ustawienia?

{-# LANGUAGE TemplateHaskell #-} 

import Language.Haskell.TH 
import Control.Lens 

data Point = P { _x :: Double, _y :: Double } deriving (Show) 
$(makeLenses ''Point) 

To właśnie staram się robić w bezwzględnej stylu:

point.set("x", g (point.get("x"))) 

Obecnie Próbowałem tej realizacji:

mapF f p g = let v = g (p ^. f) in set f v p 

To nie jest rzeczywisty skład, nie idiomatyczne, a także powoduje błąd:

Couldn't match expected type `Mutator b0' 
      with actual type `Accessor a0 a0' 
Expected type: ASetter s1 t0 a0 b0 
    Actual type: Getting a0 s0 a0 

Nawet non-parametryzowane wersja powyższego będzie działać:

mapX p g = let v = g (p^.x) in set x v p 

Wygląda f mogłyby być albo getter lub setter, a nie jedno i drugie?

Odpowiedz

8

Chcesz funkcję over, którego typ specjalizuje się w tym przypadku do:

over :: Setter a b -> (b -> b) -> a -> a 

Więc po prostu napisać:

over x :: (Double -> Double) -> Point -> Point