Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Lens, how do you compose setter with another function g such that the output of g is the new value to be set?

Tags:

haskell

Simple example:

{-# LANGUAGE TemplateHaskell #-}

import Language.Haskell.TH
import Control.Lens

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

This is what I am trying to do in imperative style:

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

Currently I tried this implementation:

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

It's not an actual composition, not idiomatic, and also throws an error:

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

Even though a non-parameterized version of the above would work:

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

It seems like f could either be a getter or setter, not both?

like image 580
xiaolingxiao Avatar asked Jun 11 '13 20:06

xiaolingxiao


1 Answers

You want the over function, whose type specializes in this case to:

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

So you would just write:

over x :: (Double -> Double) -> Point -> Point
like image 164
Gabriella Gonzalez Avatar answered Sep 23 '22 01:09

Gabriella Gonzalez