lens -package:lens

lens creates a Lens from a getter and a setter. The resulting lens isn't the most effective one (because of having to traverse the structure twice when modifying), but it shouldn't matter much. A (partial) lens for list indexing:
ix :: Int -> Lens' [a] a
ix i = lens (!! i)                                   -- getter
(\s b -> take i s ++ b : drop (i+1) s)   -- setter
Usage:
>>> [1..9] ^. ix 3
4

>>> [1..9] & ix 3 %~ negate
[1,2,3,-4,5,6,7,8,9]
When getting, the setter is completely unused; when setting, the getter is unused. Both are used only when the value is being modified. For instance, here we define a lens for the 1st element of a list, but instead of a legitimate getter we use undefined. Then we use the resulting lens for setting and it works, which proves that the getter wasn't used:
>>> [1,2,3] & lens undefined (\s b -> b : tail s) .~ 10
[10,2,3]
Build a Lens from a getter and a setter.
lens :: Functor f => (s -> a) -> (s -> b -> t) -> (a -> f b) -> s -> f t
>>> s ^. lens getter setter
getter s
>>> s & lens getter setter .~ b
setter s b
>>> s & lens getter setter %~ f
setter s (f (getter s))
lens :: (s -> a) -> (s -> a -> s) -> Lens' s a
Creates Lens' from the getter and setter.
Build a lens from a getter and a setter, which must respect the well-formedness laws. If you want to build a Lens from the van Laarhoven representation, use lensVL.
Build a lens from a getter and setter family. Caution: In order for the generated lens family to be well-defined, you must ensure that the three lens laws hold:
  • getter (setter s a) === a
  • setter s (getter s) === s
  • setter (setter s a1) a2 === setter s a2
My lens creation function to avoid a dependency on lens.
lens :: (s -> a) -> (s -> b -> t) -> Lens s t a b
Build a lens from a getter and setter family. Caution: In order for the generated lens family to be well-defined, you must ensure that the three lens laws hold:
  • getter (setter s a) === a
  • setter s (getter s) === s
  • setter (setter s a1) a2 === setter s a2
Build a lens out of a getter and setter
Make a lens out of the label. Example: over (lens #salary) (* 1.1) employee
Network uri lenses
Lens s t a b is the lowest common denominator of a setter and a getter, something that has the power of both; it has a Functor constraint, and since both Const and Identity are functors, it can be used whenever a getter or a setter is needed.
  • a is the type of the value inside of structure
  • b is the type of the replaced value
  • s is the type of the whole structure
  • t is the type of the structure after replacing a in it with b
Functions from Control.Exception.Lens, but using MonadUnliftIO, not MonadCatch
This module also exports orphan Ixed Value and Plated Value instances.
HTTP client lens machinery. When reading the examples in this module, you should assume the following environment:
-- Make it easy to write literal ByteString and Text values.
{-# LANGUAGE OverloadedStrings #-}

-- Our handy module.
import Network.Wreq

-- Operators such as (&) and (.~).
import Control.Lens

-- Conversion of Haskell values to JSON.
import Data.Aeson (toJSON)

-- Easy traversal of JSON data.
import Data.Aeson.Lens (key, nth)
This module aims to provide a minimal implementation of lens package required for basic usage. All functions are compatible with the real lens package therefore if you need to expand to the full version the process should be straightforward. Main ideas implemented in this module are described in the following blog post:

Usage

To use lenses in your project, you don't need to add any other dependency rather than relude. You should add the import of this module in the place of lenses usage:
import Relude.Extra.Lens

Example

To understand better how to use this module lets look at some simple example. Let's say we have the user data type in our system:
data User = User
{ userName    :: Text
, userAge     :: Int
, userAddress :: Address
} deriving (Show)

data Address = Address
{ addressCountry :: Text
, addressCity    :: Text
, addressIndex   :: Text
} deriving (Show)
To create the lens for the userName field we can use lens function and manually writing getter and setter function:
nameL :: Lens' User Text
nameL = lens getter setter
where
getter :: User -> Text
getter = userName

setter :: User -> Text -> User
setter user newName = user {userName = newName}
In this manner, we can create other lenses for our User data type.
ageL     :: Lens' User Int
addressL :: Lens' User Address
countryL :: Lens' User Text
cityL    :: Lens' User Text
indexL   :: Lens' User Text
Note: here we are using composition of the lenses for userAddress field. If we have
addressCityL :: Lens' Address Text
then
cityL = addressL . addressCityL
Let's say we have some sample user
user :: User
user = User
{ userName = "John"
, userAge  = 42
, userAddress = Address
{ addressCountry = "UK"
, addressCity    = "London"
, addressIndex   = "XXX"
}
}
To view the fields of the User data type we can use view or ^.
>>> view ageL user
42
>>> user ^. cityL
"London"
If we want to change any of the user's data, we should use set or .~
>>> set nameL "Johnny" user
>>> user & indexL .~ "YYY"
over or %~ operator could be useful when, for example, you want to increase the age by one on the user's birthday:
>>> over ageL succ user
>>> user & ageL %~ succ

Migration

This module is not supposed to be the replacement for the lens package. One of the reasons why one would want to migrate to lens or microlens is that the functional in relude is limited to just vital lens functions. To migrate to lens or microlens package add the required library to the dependencies list in the .cabal file and replace the import from relude library
import Relude.Extra.Lens
to the one of this correspondingly:
  • lens:
    import Control.Lens 
  • microlens:
    import Lens.Micro 
And that's all! No need to change the types or implementation of the functions you used Relude.Extra.Lens in.

Links

A Lens is actually a lens family as described in http://comonad.com/reader/2012/mirrored-lenses/. With great power comes great responsibility and a Lens is subject to the three common sense Lens laws: 1) You get back what you put in:
view l (set l v s)  ≡ v
2) Putting back what you got doesn't change anything:
set l (view l s) s  ≡ s
3) Setting twice is the same as setting once:
set l v' (set l v s) ≡ set l v' s
These laws are strong enough that the 4 type parameters of a Lens cannot vary fully independently. For more on how they interact, read the "Why is it a Lens Family?" section of http://comonad.com/reader/2012/mirrored-lenses/. There are some emergent properties of these laws: 1) set l s must be injective for every s This is a consequence of law #1 2) set l must be surjective, because of law #2, which indicates that it is possible to obtain any v from some s such that set s v = s 3) Given just the first two laws you can prove a weaker form of law #3 where the values v that you are setting match:
set l v (set l v s) ≡ set l v s
Every Lens can be used directly as a Setter or Traversal. You can also use a Lens for Getting as if it were a Fold or Getter. Since every Lens is a valid Traversal, the Traversal laws are required of any Lens you create:
l purepure
fmap (l f) . l g ≡ getCompose . l (Compose . fmap f . g)
type Lens s t a b = forall f. Functor f => LensLike f s t a b
Lenses into record fields.
Lens s t a b is the lowest common denominator of a setter and a getter, something that has the power of both; it has a Functor constraint, and since both Const and Identity are functors, it can be used whenever a getter or a setter is needed.
  • a is the type of the value inside of structure
  • b is the type of the replaced value
  • s is the type of the whole structure
  • t is the type of the structure after replacing a in it with b
Extra utilities from microlens. @since: 0.1.16.0
A Lens is a generalised or first-class field. If we have a value s :: S, and a l :: Lens' S A, we can get the "field value" of type A using view l s. We can also update (or put or set) the value using over (or set). For example, given the following definitions:
>>> data Human = Human { _name :: String, _location :: String } deriving Show

>>> let human = Human "Bob" "London"
we can make a Lens for _name field:
>>> let name = lens _name $ \s x -> s { _name = x }
which we can use as a Getter:
>>> view name human
"Bob"
or a Setter:
>>> set name "Robert" human
Human {_name = "Robert", _location = "London"}
Type synonym for a type-modifying lens.