| Copyright | (C) 2016-2026 David M. Johnson |
|---|---|
| License | BSD3-style (see the file LICENSE) |
| Maintainer | David M. Johnson <code@dmj.io> |
| Stability | experimental |
| Portability | non-portable |
| Safe Haskell | Safe-Inferred |
| Language | Haskell2010 |
Miso.Lens
Description
A simple Lens formulation compatible with lens and microlens.
The Lens type is defined as:
dataLensrecord field =Lens{_get:: record -> field ,_set:: record -> field -> record }
Key features:
- Provides an out-of-the-box lens experience with a minimal dependency footprint.
- Uses a simple formulation (not van Laarhoven) for smaller compilation payload.
- Import separately:
import Miso.Lens. - Works with the
Effectmonad inside miso applications. - Fixity and interface parity with
lensandmicrolens; replaceimport Miso.Lenswithimport Control.Lensto switch seamlessly. - Re-exports
Lens'for easy migration to lens or microlens.
For more on the van Laarhoven formulation, see the lens library.
Example: Lenses for a nested record
data Person = Person
{ _name :: String
, _address :: Address
, _age :: Int
} deriving (Show, Eq, Generic)
newtype Address
= Address
{ _zipCode :: Zip
} deriving (Show, Eq)
type Zip = String
name :: Lens Person String
name = lens _name $ \record x -> record { _name = x }
address :: Lens Person Address
address = lens _address $ \record x -> record { _address = x }
zipCode :: Lens Address Zip
zipCode = lens _zipCode $ \record x -> record { _zipCode = x }
-- Lenses compose via .
personZip :: Lens Person Zip
personZip = zipCode . address
main :: IO ()
main = print $ person & address .~ Address "10012"
-- Person { _name = "john", _age = 33, _address = Address {_zipCode = "10012"} }
Example: Usage with the Effect monad
newtype Model = Model { _value :: Int }
value :: Lens Model Int
value = lens _value $ \model v -> model { _value = v }
data Action = AddOne | SubtractOne
updateModel :: Action -> Effect parent Model Action
updateModel = \case
AddOne -> value += 1
SubtractOne -> value -= 1
Synopsis
- type Lens s a = LensCore a s
- data LensCore field record = Lens {}
- data Prism s a = Prism {}
- lens :: (record -> field) -> (record -> field -> record) -> Lens record field
- prism :: (a -> s) -> (s -> Maybe a) -> Prism s a
- (&) :: a -> (a -> b) -> b
- (<&>) :: Functor f => f a -> (a -> b) -> f b
- (.~) :: Lens record field -> field -> record -> record
- (?~) :: Lens record (Maybe field) -> field -> record -> record
- set :: Lens record field -> field -> record -> record
- (%~) :: Lens record field -> (field -> field) -> record -> record
- over :: Lens record field -> (field -> field) -> record -> record
- (^.) :: record -> Lens record field -> field
- (+~) :: Num field => Lens record field -> field -> record -> record
- (*~) :: Num field => Lens record field -> field -> record -> record
- (//~) :: Fractional field => Lens record field -> field -> record -> record
- (-~) :: Num field => Lens record field -> field -> record -> record
- (%=) :: MonadState record m => Lens record field -> (field -> field) -> m ()
- (%?=) :: MonadState record m => Lens record (Maybe field) -> (field -> field) -> m ()
- modifying :: MonadState record m => Lens record field -> (field -> field) -> m ()
- (+=) :: (MonadState record m, Num field) => Lens record field -> field -> m ()
- (*=) :: (MonadState record m, Num field) => Lens record field -> field -> m ()
- (//=) :: (MonadState record m, Fractional field) => Lens record field -> field -> m ()
- (-=) :: (MonadState record m, Num field) => Lens record field -> field -> m ()
- (.=) :: MonadState record m => Lens record field -> field -> m ()
- (<~) :: MonadState record m => Lens record field -> m field -> m ()
- (<%=) :: MonadState record m => Lens record field -> (field -> field) -> m field
- (<.=) :: MonadState record m => Lens record field -> field -> m field
- (<?=) :: MonadState record m => Lens record (Maybe field) -> field -> m field
- (<<.=) :: MonadState record m => Lens record field -> field -> m field
- (<<%=) :: MonadState record m => Lens record field -> (field -> field) -> m field
- assign :: MonadState record m => Lens record field -> field -> m ()
- use :: MonadState record m => Lens record field -> m field
- view :: MonadReader record m => Lens record field -> m field
- (?=) :: MonadState record m => Lens record (Maybe field) -> field -> m ()
- (<>~) :: Monoid field => Lens record field -> field -> record -> record
- _1 :: Lens (a, b) a
- _2 :: Lens (a, b) b
- _id :: Lens a a
- this :: Lens a a
- preview :: MonadReader r m => Prism r a -> m (Maybe a)
- preuse :: MonadState s m => Prism s a -> m (Maybe a)
- review :: Prism s a -> a -> s
- _Nothing :: Prism (Maybe a) a
- _Just :: Prism (Maybe a) a
- _Left :: Prism (Either a b) a
- _Right :: Prism (Either a b) b
- (^?) :: s -> Prism s a -> Maybe a
- class At at where
- compose :: Category cat => cat a b -> cat b c -> cat a c
- type Lens' s a = forall (f :: Type -> Type). Functor f => (a -> f a) -> s -> f s
- toVL :: Lens record field -> Lens' record field
- fromVL :: Lens' record field -> Lens record field
Types
type Lens s a = LensCore a s Source #
A Lens is a generalized getter and setter.
Lenses allow both the retrieval of values from fields in a record and the
assignment of values to fields in a record. The power of a Lens comes
from its ability to be composed with other lenses.
In the context of building applications with miso, the model is
often a deeply nested product type. This makes it highly conducive
to Lens operations (as defined below).
data LensCore field record Source #
LensCore is an internal type used to reverse composition like
VL libraries do.
Constructors
| Lens | |
Instances
Smart constructor
Arguments
| :: (record -> field) | Getter: read the field from a record |
| -> (record -> field -> record) | Setter: write a new field value into a record |
| -> Lens record field |
Arguments
| :: (a -> s) | Embed direction: construct |
| -> (s -> Maybe a) | Match direction: try to extract |
| -> Prism s a |
Smart constructor for Prism.
Re-exports
(&) :: a -> (a -> b) -> b infixl 1 #
& is a reverse application operator. This provides notational
convenience. Its precedence is one higher than that of the forward
application operator $, which allows & to be nested in $.
This is a version of , where flip idid is specialized from a -> a to (a -> b) -> (a -> b)
which by the associativity of (->) is (a -> b) -> a -> b.
flipping this yields a -> (a -> b) -> b which is the type signature of &
Examples
>>>5 & (+1) & show"6"
>>>sqrt $ [1 / n^2 | n <- [1..1000]] & sum & (*6)3.1406380562059946
Since: base-4.8.0.0
Lens Combinators
(.~) :: Lens record field -> field -> record -> record infixr 4 Source #
Set a field on a record
newtype Person = Person { _name :: String }
name :: Lens Person String
name = lens _name $ \person n -> person { _name = n }
setName :: Person -> String -> Person
setName person newName = person & name .~ newName
(?~) :: Lens record (Maybe field) -> field -> record -> record infixr 4 Source #
Set an options field on a record
newtype Person = Person { _name :: Maybe String }
name :: Lens Person (Maybe String)
name = lens _name $ \person n -> person { _name = n }
setName :: Person -> String -> Person
setName person newName = person & name ?~ newName
(%~) :: Lens record field -> (field -> field) -> record -> record infixr 4 Source #
Modify a field on a record by applying a function to it.
newtype Counter = Counter { _value :: Int }
value :: Lens Counter Int
value = lens _value $ \counter v -> counter { _value = v }
increment :: Counter -> Counter
increment counter = counter & value %~ (+1)
(^.) :: record -> Lens record field -> field infixl 8 Source #
Read a field from a record using a Lens
newtype Person = Person { _name :: String }
deriving (Show, Eq)
name :: Lens Person String
name = lens _name $ \person n -> person { _name = n }
getName :: Person -> String
getName = person ^. name
(+~) :: Num field => Lens record field -> field -> record -> record infixr 4 Source #
Increment a Num field => field on a record using a Lens
newtype Person = Person { _age :: Int }
age :: Lens Person Int
age = lens _age $ \person a -> person { _age = a }
birthday :: Person -> Person
birthday person = person & age +~ 1
(*~) :: Num field => Lens record field -> field -> record -> record infixr 4 Source #
Multiply a Numeric field on a record using a Lens
newtype Circle = Circle { _radius :: Int }
radius :: Lens Circle Int
radius = lens _radius $ \circle r -> circle { _radius = r }
expand :: Circle -> Circle
expand circle = circle & radius *~ 10
(//~) :: Fractional field => Lens record field -> field -> record -> record infixr 4 Source #
Divide a Fractional field on a record using a Lens
newtype Circle = Circle { _radius :: Int }
radius :: Lens Circle Int
radius = lens _radius $ \circle r -> circle { _radius = r }
shrink :: Circle -> Circle
shrink circle = circle & radius //~ 10
(-~) :: Num field => Lens record field -> field -> record -> record infixr 4 Source #
Increment a Numeric field on a record using a Lens
newtype Person = Person { _age :: Int }
age :: Lens Person Int
age = lens _age $ \person a -> person { _age = a }
timeTravel :: Person -> Person
timeTravel person = person & age -~ 1
(%=) :: MonadState record m => Lens record field -> (field -> field) -> m () infix 4 Source #
Modify a record in MonadState monad at a field using a Lens
newtype Model = Model { _value :: Int }
data Action = AddOne | SubtractOne
value :: Lens Model Int
value = lens _value $ \p x -> p { _value = x }
update :: Action -> Effect parent Model Action
update AddOne = do
value %= (+1)
(%?=) :: MonadState record m => Lens record (Maybe field) -> (field -> field) -> m () infix 4 Source #
Alters the Just value of a field in a record using a Lens inside a MonadState
newtype Model = Model { _value :: Maybe Int }
deriving (Show, Eq)
data Action = IncrementIfJust
value :: Lens Model (Maybe Int)
value = lens _value $ \p x -> p { _value = x }
update :: Action -> Effect parent Model Action
update IncrementIfJust = value %?= (+1)
modifying :: MonadState record m => Lens record field -> (field -> field) -> m () Source #
Synonym for (%=)
(+=) :: (MonadState record m, Num field) => Lens record field -> field -> m () infix 4 Source #
Increments the value of a Numeric field of a record using a Lens
inside a State Monad.
newtype Model = Model { _value :: Int }
deriving (Show, Eq)
data Action = IncrementBy Int
value :: Lens Model Int
value = lens _value $ \p x -> p { _value = x }
update :: Action -> Effect parent Model Action
update (IncrementBy x) = value += x
(*=) :: (MonadState record m, Num field) => Lens record field -> field -> m () infix 4 Source #
Multiplies the value of a Numeric field of a record using a Lens
inside a State Monad.
newtype Model = Model { _value :: Int }
deriving (Show, Eq)
data Action = MultiplyBy Int
value :: Lens Model Int
value = lens _value $ \p x -> p { _value = x }
update :: Action -> Effect parent Model Action
update (MultiplyBy x) = value *= x
(//=) :: (MonadState record m, Fractional field) => Lens record field -> field -> m () infix 4 Source #
Divides the value of a Fractional field of a record using a Lens
inside a State Monad.
newtype Model = Model { _value :: Double }
deriving (Show, Eq)
data Action = DivideBy Double
value :: Lens Model Double
value = lens _value $ \p x -> p { _value = x }
update :: Action -> Effect parent Model Action
update (DivideBy x) = value //= x
(-=) :: (MonadState record m, Num field) => Lens record field -> field -> m () infix 4 Source #
Subtracts the value of a Numeric field of a record using a Lens
inside of a State Monad.
newtype Model = Model { _value :: Double }
deriving (Show, Eq)
data Action = SubtractBy Double
value :: Lens Model Double
value = lens _value $ \p x -> p { _value = x }
update :: Action -> Effect parent Model Action
update (SubtractBy x) = value -= x
(.=) :: MonadState record m => Lens record field -> field -> m () infix 4 Source #
Sets the value of a field in a record using MonadState and a Lens
newtype Model = Model { _value :: Int }
deriving (Show, Eq)
data Action = SetValue Int
value :: Lens Model Int
value = lens _value $ \p x -> p { _value = x }
update' :: Action -> Effect parent Model Action
update' (SetValue v) = value .= v
(<~) :: MonadState record m => Lens record field -> m field -> m () infixr 2 Source #
Execute a monadic action in MonadState that returns a field. Sets the
return value equal to the field in the record.
As a reasonable mnemonic, this lets you store the result of a monadic action in a Lens rather than
in a local variable.
do foo <- bar ...
will store the result in a variable, while
do fooLens <~ bar
...
will store the result in field focused by the Lens.
(<%=) :: MonadState record m => Lens record field -> (field -> field) -> m field infix 4 Source #
Modify the field of a record in MonadState using a Lens, then
return the newly modified field from the updated record.
import Miso.String (ms)
newtype Model = Model { _value :: Int }
deriving (Show)
data Action = AddOne
value :: Lens Model Int
value = lens _value $ \p x -> p { _value = x }
update :: Action -> Effect parent Model Action
update AddOne = do
result <- value <%= (+1)
io_ $ consoleLog (ms result)
(<.=) :: MonadState record m => Lens record field -> field -> m field infix 4 Source #
Assign the field of a record in MonadState to a value using a Lens
Return the value after assignment.
import Miso.String (ms)
newtype Model = Model { _value :: Int }
data Action = Assign Int
value :: Lens Model Int
value = lens _value $ \p x -> p { _value = x }
update :: Action -> Effect parent Model Action
update (Assign x) = do
result <- value <.= x
io_ $ consoleLog (ms result) -- x
(<?=) :: MonadState record m => Lens record (Maybe field) -> field -> m field infix 4 Source #
Assign the field of a record in a MonadState to a value (wrapped in a Just)
using a Lens. Return the value after assignment.
import Miso.String (ms)
newtype Model = Model { _value :: Maybe Int }
data Action = SetValue Int
value :: Lens Model (Maybe Int)
value = lens _value $ \p x -> p { _value = x }
update :: Action -> Effect parent Model Action
update (SetValue x) = do
result <- value <?= x
io_ $ consoleLog (ms result) -- Just 1
(<<.=) :: MonadState record m => Lens record field -> field -> m field infix 4 Source #
Assign the field of a record in a MonadState to a value using a Lens.
Returns the previous value, before assignment.
import Miso.String (ms)
newtype Model = Model { _value :: Int }
deriving (Show, Eq)
data Action = Assign Int
deriving (Show, Eq)
value :: Lens Model Int
value = lens _value $ \p x -> p { _value = x }
update :: Action -> Effect parent Model Action
update (Assign x) = do
value .= x
previousValue <- value <<.= 1
io_ $ consoleLog $ ms previousValue -- prints value at x
(<<%=) :: MonadState record m => Lens record field -> (field -> field) -> m field infix 4 Source #
Modifies the field of a record in MonadState using a Lens.
Returns the previous value, before modification.
import Miso.String (ms)
newtype Model = Model { _value :: Int }
deriving (Show, Eq)
data Action = Modify (Int -> Int)
value :: Lens Model Int
value = lens _value $ \p x -> p { _value = x }
update :: Action -> Effect parent Model Action
update (Modify f) = do
value .= 2
result <- value <<%= f
io_ $ consoleLog (ms result) -- prints previous value of 2
use :: MonadState record m => Lens record field -> m field Source #
Retrieves the value of a field in a record using a Lens inside MonadState
import Miso.String (ms)
newtype Model = Model { _value :: Int }
deriving (Show, Eq)
data Action = SetValue Int
value :: Lens Model Int
value = lens _value $ \p x -> p { _value = x }
update :: Action -> Effect parent Model Action
update (SetValue x) = do
value .= x
result <- use value
io_ $ consoleLog (ms result) -- prints the value of x
view :: MonadReader record m => Lens record field -> m field Source #
Retrieves the field associated with a record in MonadReader using a Lens.
import Miso.String (ms)
newtype Model = Model { _value :: Int }
deriving (Show, Eq)
data Action = PrintInt
value :: Lens Model Int
value = lens _value $ \p x -> p { _value = x }
update :: Action -> Effect parent Model Action
update PrintInt = do
Model x <- view value
io_ $ consoleLog (ms x) -- prints model value
(?=) :: MonadState record m => Lens record (Maybe field) -> field -> m () infix 4 Source #
Sets the value of a field in a record using a Lens inside a MonadState
The value is wrapped in a Just before being assigned.
newtype Model = Model { _value :: Maybe Int }
deriving (Show, Eq)
data Action = AssignValue Int
value :: Lens Model (Maybe Int)
value = lens _value $ \p x -> p { _value = x }
update :: Action -> Effect parent Model Action
update (AssignValue x) = value ?= x
(<>~) :: Monoid field => Lens record field -> field -> record -> record infixr 4 Source #
Monoidally append a field in a record using a Lens
newtype List = List { _values :: [Int] }
values :: Lens List [Int]
values = lens _values $ \l vs -> l { _values = vs }
addElement :: List -> List
addElement list = list & values <>~ [2]
addElement (List [])
-- List [2]
Prism Combinators
preview :: MonadReader r m => Prism r a -> m (Maybe a) Source #
Try to extract a value from a sum type using a Prism inside MonadReader.
preuse :: MonadState s m => Prism s a -> m (Maybe a) Source #
Try to extract a value from a sum type using a Prism inside MonadState.
Containers
Class for getting and setting values across various container types.
M.singleton 'a' "foo" & at 'a' .~ Just "bar"
-- fromList [('a',"bar")]update (SetValue value) at 10 ?= value
Since: 1.9.0.0
Associated Types
Index of the container
Indexed value of the container
Re-exports
compose :: Category cat => cat a b -> cat b c -> cat a c Source #
Function composition generalized to Category
test :: Int -> Int test = (+1) `compose` (+1)