----------------------------------------------------------------------------- -- | -- Module : Miso.Lens -- Copyright : (C) 2016-2025 David M. Johnson -- License : BSD3-style (see the file LICENSE) -- Maintainer : David M. Johnson <code@dmj.io> -- Stability : experimental -- Portability : non-portable -- -- This modules exposes a very simple 'Lens' formulation that is compatible with other lens libraries. -- -- For state management of miso applications, this module should meet all of your needs. It also -- ensures a smaller payload size during compilation. -- -- @ -- data Lens record field -- = Lens -- { _get :: record -> field -- , _set :: record -> field -> record -- } -- @ -- -- The goal is to provide users with an out-of-the box lens experience without the large -- dependency footprint and cognitive load. This module also aims to preserve semantics of -- existing lens combinators using a simple formulation (not the Van Laarhoven). It must be imported -- separately (@import Miso.Lens@) and can be used with the @Effect@ Monad inside of a miso -- application (as described below). -- -- This module is at fixity and interface parity with @lens@ and @microlens@ and can therefore -- be used interchangeably with them. Simply replace the @Miso.Lens@ import with @Control.Lens@. -- For convenience we re-export the 'Lens'' synonym to ease the transition into @lens@ or -- @microlens@. -- -- For the curious reader, if you'd like more information on @lens@ and the Van Laarhoven -- formulation, we recommend the @lens@ library <https://hackage.haskell.org/package/lens>. -- -- @ -- -- Person type -- data Person = Person -- { _name :: String -- , _address :: Address -- , _age :: Int -- } deriving (Show, Eq, Generic) -- -- -- Address type -- newtype Address -- = Address -- { _zipCode :: Zip -- } deriving (Show, Eq) -- -- -- | Zip code type synonym -- type Zip = String -- -- -- | Name Lens -- name :: Lens Person String -- name = 'lens' _name $ \\record x -> record { _name = x } -- -- -- | Address Lens -- address :: Lens Person Address -- address = 'lens' _address $ \\record x -> record { _address = x } -- -- -- | Zip Code Lens -- zipCode :: Lens Address Zip -- zipCode = 'lens' _zipCode $ \\record x -> record { _zipCode = x } -- -- -- | Lens Composition example -- personZip :: Lens Person Zip -- personZip = zipCode . address -- -- -- | Person example -- person :: Person -- person = Person "john" (Address "90210") 33 -- -- main :: IO () -- main = print $ john '&' address '.~' Address "10012" -- -- > Person -- > { _name = "john" -- > , _age = 33 -- > , _address = Address {_zipCode = "10012"} -- > } -- @ -- -- Example usage with miso's @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' Model Action -- updateModel AddOne = value '+=' 1 -- updateModel SubtractOne = value '-=' 1 -- @ ---------------------------------------------------------------------------- module Miso.Lens ( -- ** Types Lens (..) , Lens' -- ** Smart constructor , lens -- ** Re-exports , (&) , (<&>) -- ** Combinators , (.~) , (?~) , set , (%~) , over , (^.) , (+~) , (*~) , (//~) , (-~) , (%=) , modifying , (+=) , (*=) , (//=) , (-=) , (.=) , (<~) , (<%=) , (<.=) , (<?=) , (<<.=) , (<<%=) , assign , use , (?=) , (<>~) ) where ---------------------------------------------------------------------------- import Control.Monad.State (MonadState, modify, gets) import Control.Category (Category (..)) import Control.Arrow ((<<<)) import Data.Function ((&)) import Data.Functor((<&>)) ---------------------------------------------------------------------------- -- | 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 Lens record field = Lens { forall record field. Lens record field -> record -> field _get :: record -> field -- ^ Retrieves a field from a record , forall record field. Lens record field -> record -> field -> record _set :: record -> field -> record -- ^ Sets a field on a record } ---------------------------------------------------------------------------- -- | Type synonym re-export for @lens@ / @microlens@ compatability. -- Note: use this if you plan on migrating to lens or microlens eventually. -- Just use @Lens@ otherwise (as examples show). type Lens' record field = Lens record field ---------------------------------------------------------------------------- -- | Lens are Categories, and can therefore be composed. instance Category Lens where id :: forall a. Lens a a id = (a -> a) -> (a -> a -> a) -> Lens a a forall record field. (record -> field) -> (record -> field -> record) -> Lens record field Lens (\a x -> a x) (\a x a _ -> a x) Lens b -> c g1 b -> c -> b s1 . :: forall b c a. Lens b c -> Lens a b -> Lens a c . Lens a -> b g2 a -> b -> a s2 = Lens { _get :: a -> c _get = b -> c g1 (b -> c) -> (a -> b) -> a -> c forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k). Category cat => cat b c -> cat a b -> cat a c <<< a -> b g2 , _set :: a -> c -> a _set = \a r c f -> a -> b -> a s2 a r (b -> c -> b s1 (a -> b g2 a r) c f) } ---------------------------------------------------------------------------- -- | 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 -- @ infixr 4 .~ (.~) :: Lens record field -> field -> record -> record .~ :: forall record field. Lens record field -> field -> record -> record (.~) Lens record field _lens = (record -> field -> record) -> field -> record -> record forall a b c. (a -> b -> c) -> b -> a -> c flip (Lens record field -> record -> field -> record forall record field. Lens record field -> record -> field -> record _set Lens record field _lens) ---------------------------------------------------------------------------- -- | Synonym for '(.~)' -- set :: Lens record field -> field -> record -> record set :: forall record field. Lens record field -> field -> record -> record set = Lens record field -> field -> record -> record forall record field. Lens record field -> field -> record -> record (.~) ---------------------------------------------------------------------------- -- | 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 -- @ infixr 4 ?~ (?~) :: Lens record (Maybe field) -> field -> record -> record ?~ :: forall record field. Lens record (Maybe field) -> field -> record -> record (?~) Lens record (Maybe field) _lens field f record r = record r record -> (record -> record) -> record forall a b. a -> (a -> b) -> b & Lens record (Maybe field) _lens Lens record (Maybe field) -> Maybe field -> record -> record forall record field. Lens record field -> field -> record -> record .~ field -> Maybe field forall a. a -> Maybe a Just field f ---------------------------------------------------------------------------- -- | 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) -- @ infixr 4 %~ (%~) :: Lens record field -> (field -> field) -> record -> record %~ :: forall record field. Lens record field -> (field -> field) -> record -> record (%~) Lens record field _lens field -> field f record record = Lens record field -> record -> field -> record forall record field. Lens record field -> record -> field -> record _set Lens record field _lens record record (field -> record) -> field -> record forall a b. (a -> b) -> a -> b $ field -> field f (record record record -> Lens record field -> field forall record field. record -> Lens record field -> field ^. Lens record field _lens) ---------------------------------------------------------------------------- -- | Synonym for '(%~)' over :: Lens record field -> (field -> field) -> record -> record over :: forall record field. Lens record field -> (field -> field) -> record -> record over = Lens record field -> (field -> field) -> record -> record forall record field. Lens record field -> (field -> field) -> record -> record (%~) ---------------------------------------------------------------------------- -- | 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 -- @ infixl 8 ^. (^.) :: record -> Lens record field -> field ^. :: forall record field. record -> Lens record field -> field (^.) = (Lens record field -> record -> field) -> record -> Lens record field -> field forall a b c. (a -> b -> c) -> b -> a -> c flip Lens record field -> record -> field forall record field. Lens record field -> record -> field _get ---------------------------------------------------------------------------- -- | Increment a @Num@eric 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 -- @ infixr 4 +~ (+~) :: Num field => Lens record field -> field -> record -> record +~ :: forall field record. Num field => Lens record field -> field -> record -> record (+~) Lens record field _lens field x record record = record record record -> (record -> record) -> record forall a b. a -> (a -> b) -> b & Lens record field _lens Lens record field -> (field -> field) -> record -> record forall record field. Lens record field -> (field -> field) -> record -> record %~ (field -> field -> field forall a. Num a => a -> a -> a +field x) ---------------------------------------------------------------------------- -- | Multiply a @Num@eric 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 -- @ infixr 4 *~ (*~) :: Num field => Lens record field -> field -> record -> record *~ :: forall field record. Num field => Lens record field -> field -> record -> record (*~) Lens record field _lens field x record record = record record record -> (record -> record) -> record forall a b. a -> (a -> b) -> b & Lens record field _lens Lens record field -> (field -> field) -> record -> record forall record field. Lens record field -> (field -> field) -> record -> record %~ (field -> field -> field forall a. Num a => a -> a -> a *field x) ---------------------------------------------------------------------------- -- | 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 } -- -- expand :: Circle -> Circle -- expand circle = circle & radius *~ 10 -- @ infixr 4 //~ (//~) :: Fractional field => Lens record field -> field -> record -> record //~ :: forall field record. Fractional field => Lens record field -> field -> record -> record (//~) Lens record field _lens field x record record = record record record -> (record -> record) -> record forall a b. a -> (a -> b) -> b & Lens record field _lens Lens record field -> (field -> field) -> record -> record forall record field. Lens record field -> (field -> field) -> record -> record %~ (field -> field -> field forall a. Fractional a => a -> a -> a /field x) ---------------------------------------------------------------------------- -- | Increment a @Num@eric 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 -- @ infixr 4 -~ (-~) :: Num field => Lens record field -> field -> record -> record -~ :: forall field record. Num field => Lens record field -> field -> record -> record (-~) Lens record field _lens field x record record = record record record -> (record -> record) -> record forall a b. a -> (a -> b) -> b & Lens record field _lens Lens record field -> (field -> field) -> record -> record forall record field. Lens record field -> (field -> field) -> record -> record %~ field -> field -> field forall a. Num a => a -> a -> a subtract field x ---------------------------------------------------------------------------- -- | 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] -- @ -- infixr 4 <>~ (<>~) :: Monoid field => Lens record field -> field -> record -> record <>~ :: forall field record. Monoid field => Lens record field -> field -> record -> record (<>~) Lens record field _lens field x record record = record record record -> (record -> record) -> record forall a b. a -> (a -> b) -> b & Lens record field _lens Lens record field -> (field -> field) -> record -> record forall record field. Lens record field -> (field -> field) -> record -> record %~ (field -> field -> field forall a. Semigroup a => a -> a -> a <> field x) ---------------------------------------------------------------------------- -- | Execute a monadic action in @MonadState@ that returns a field. Sets the -- return value equal to the field in the record. -- -- @ -- 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] -- @ infixr 2 <~ (<~) :: MonadState record m => Lens record field -> m field -> m () Lens record field l <~ :: forall record (m :: * -> *) field. MonadState record m => Lens record field -> m field -> m () <~ m field mb = do b <- m field mb l .= b ---------------------------------------------------------------------------- -- | 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 Model Action -- update AddOne = do -- value %= (+1) -- @ infix 4 %= (%=) :: MonadState record m => Lens record field -> (field -> field) -> m () %= :: forall record (m :: * -> *) field. MonadState record m => Lens record field -> (field -> field) -> m () (%=) Lens record field _lens field -> field f = (record -> record) -> m () forall s (m :: * -> *). MonadState s m => (s -> s) -> m () modify (\record r -> record r record -> (record -> record) -> record forall a b. a -> (a -> b) -> b & Lens record field _lens Lens record field -> (field -> field) -> record -> record forall record field. Lens record field -> (field -> field) -> record -> record %~ field -> field f) ---------------------------------------------------------------------------- -- | Synonym for '(%=)' modifying :: MonadState record m => Lens record field -> (field -> field) -> m () modifying :: forall record (m :: * -> *) field. MonadState record m => Lens record field -> (field -> field) -> m () modifying = Lens record field -> (field -> field) -> m () forall record (m :: * -> *) field. MonadState record m => Lens record field -> (field -> field) -> m () (%=) ---------------------------------------------------------------------------- -- | 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 Model Action -- update AddOne = do -- result <- value <%= (+1) -- io $ consoleLog (ms result) -- @ infix 4 <%= (<%=) :: MonadState record m => Lens record field -> (field -> field) -> m field Lens record field l <%= :: forall record (m :: * -> *) field. MonadState record m => Lens record field -> (field -> field) -> m field <%= field -> field f = do Lens record field l Lens record field -> (field -> field) -> m () forall record (m :: * -> *) field. MonadState record m => Lens record field -> (field -> field) -> m () %= field -> field f Lens record field -> m field forall record (m :: * -> *) field. MonadState record m => Lens record field -> m field use Lens record field l ---------------------------------------------------------------------------- -- | 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 Model Action -- update (Assign x) = do -- result <- value <.= x -- io $ consoleLog (ms result) -- x -- @ infix 4 <.= (<.=) :: MonadState record m => Lens record field -> field -> m field Lens record field l <.= :: forall record (m :: * -> *) field. MonadState record m => Lens record field -> field -> m field <.= field b = do Lens record field l Lens record field -> field -> m () forall record (m :: * -> *) field. MonadState record m => Lens record field -> field -> m () .= field b field -> m field forall a. a -> m a forall (m :: * -> *) a. Monad m => a -> m a return field b ---------------------------------------------------------------------------- -- | 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 Model Action -- update (SetValue x) = do -- result <- value <?= x -- io $ consoleLog (ms result) -- Just 1 -- @ infix 4 <?= (<?=) :: MonadState record m => Lens record (Maybe field) -> field -> m field Lens record (Maybe field) l <?= :: forall record (m :: * -> *) field. MonadState record m => Lens record (Maybe field) -> field -> m field <?= field b = do Lens record (Maybe field) l Lens record (Maybe field) -> Maybe field -> m () forall record (m :: * -> *) field. MonadState record m => Lens record field -> field -> m () .= field -> Maybe field forall a. a -> Maybe a Just field b field -> m field forall a. a -> m a forall (m :: * -> *) a. Monad m => a -> m a return field b ---------------------------------------------------------------------------- -- | 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 Model Action -- update (Assign x) = do -- value .= x -- previousValue <- value <<.= 1 -- io $ consoleLog $ ms previousValue -- prints value at x -- @ infix 4 <<.= (<<.=) :: MonadState record m => Lens record field -> field -> m field Lens record field l <<.= :: forall record (m :: * -> *) field. MonadState record m => Lens record field -> field -> m field <<.= field b = do old <- Lens record field -> m field forall record (m :: * -> *) field. MonadState record m => Lens record field -> m field use Lens record field l l .= b return old ---------------------------------------------------------------------------- -- | 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 Model Action -- update (Modify f) = do -- value .= 2 -- result <- value <<%= f -- io $ consoleLog (ms result) -- prints previous value of 2 -- @ infix 4 <<%= (<<%=) :: MonadState record m => Lens record field -> (field -> field) -> m field Lens record field l <<%= :: forall record (m :: * -> *) field. MonadState record m => Lens record field -> (field -> field) -> m field <<%= field -> field f = do old <- Lens record field -> m field forall record (m :: * -> *) field. MonadState record m => Lens record field -> m field use Lens record field l l %= f return old ---------------------------------------------------------------------------- -- | 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 Model Action -- update' (SetValue v) = value .= v -- @ infix 4 .= (.=) :: MonadState record m => Lens record field -> field -> m () .= :: forall record (m :: * -> *) field. MonadState record m => Lens record field -> field -> m () (.=) Lens record field _lens field f = (record -> record) -> m () forall s (m :: * -> *). MonadState s m => (s -> s) -> m () modify (\record r -> record r record -> (record -> record) -> record forall a b. a -> (a -> b) -> b & Lens record field _lens Lens record field -> field -> record -> record forall record field. Lens record field -> field -> record -> record .~ field f) ---------------------------------------------------------------------------- -- | Synonym for '(.=)' assign :: MonadState record m => Lens record field -> field -> m () assign :: forall record (m :: * -> *) field. MonadState record m => Lens record field -> field -> m () assign = Lens record field -> field -> m () forall record (m :: * -> *) field. MonadState record m => Lens record field -> field -> m () (.=) ---------------------------------------------------------------------------- -- | 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 Model Action -- update (SetValue x) = do -- value .= x -- result <- use value -- io $ consoleLog (ms result) -- prints the value of 'x' -- @ use :: MonadState record m => Lens record field -> m field use :: forall record (m :: * -> *) field. MonadState record m => Lens record field -> m field use Lens record field _lens = (record -> field) -> m field forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a gets (record -> Lens record field -> field forall record field. record -> Lens record field -> field ^. Lens record field _lens) ---------------------------------------------------------------------------- -- | 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 Model Action -- update (AssignValue x) = value ?= x -- @ infix 4 ?= (?=) :: MonadState record m => Lens record (Maybe field) -> field -> m () ?= :: forall record (m :: * -> *) field. MonadState record m => Lens record (Maybe field) -> field -> m () (?=) Lens record (Maybe field) _lens field value = Lens record (Maybe field) _lens Lens record (Maybe field) -> Maybe field -> m () forall record (m :: * -> *) field. MonadState record m => Lens record field -> field -> m () .= field -> Maybe field forall a. a -> Maybe a Just field value ---------------------------------------------------------------------------- -- | Increments the value of a @Num@eric 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 Model Action -- update (IncrementBy x) = value += x -- infix 4 += (+=) :: (MonadState record m, Num field) => Lens record field -> field -> m () += :: forall record (m :: * -> *) field. (MonadState record m, Num field) => Lens record field -> field -> m () (+=) Lens record field _lens field f = (record -> record) -> m () forall s (m :: * -> *). MonadState s m => (s -> s) -> m () modify (\record r -> record r record -> (record -> record) -> record forall a b. a -> (a -> b) -> b & Lens record field _lens Lens record field -> field -> record -> record forall field record. Num field => Lens record field -> field -> record -> record +~ field f) ---------------------------------------------------------------------------- -- | Multiplies the value of a @Num@eric 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 Model Action -- update (MultiplyBy x) = value *= x -- @ infix 4 *= (*=) :: (MonadState record m, Num field) => Lens record field -> field -> m () *= :: forall record (m :: * -> *) field. (MonadState record m, Num field) => Lens record field -> field -> m () (*=) Lens record field _lens field f = (record -> record) -> m () forall s (m :: * -> *). MonadState s m => (s -> s) -> m () modify (\record r -> record r record -> (record -> record) -> record forall a b. a -> (a -> b) -> b & Lens record field _lens Lens record field -> field -> record -> record forall field record. Num field => Lens record field -> field -> record -> record *~ field f) ---------------------------------------------------------------------------- -- | 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 Model Action -- update (DivideBy x) = value //= x -- @ infix 4 //= (//=) :: (MonadState record m, Fractional field) => Lens record field -> field -> m () //= :: forall record (m :: * -> *) field. (MonadState record m, Fractional field) => Lens record field -> field -> m () (//=) Lens record field _lens field f = (record -> record) -> m () forall s (m :: * -> *). MonadState s m => (s -> s) -> m () modify (\record r -> record r record -> (record -> record) -> record forall a b. a -> (a -> b) -> b & Lens record field _lens Lens record field -> (field -> field) -> record -> record forall record field. Lens record field -> (field -> field) -> record -> record %~ (field -> field -> field forall a. Fractional a => a -> a -> a / field f)) ---------------------------------------------------------------------------- -- | Subtracts the value of a @Num@eric 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 Model Action -- update (SubtractBy x) = value -= x -- @ infix 4 -= (-=) :: (MonadState record m, Num field) => Lens record field -> field -> m () -= :: forall record (m :: * -> *) field. (MonadState record m, Num field) => Lens record field -> field -> m () (-=) Lens record field _lens field f = (record -> record) -> m () forall s (m :: * -> *). MonadState s m => (s -> s) -> m () modify (\record r -> record r record -> (record -> record) -> record forall a b. a -> (a -> b) -> b & Lens record field _lens Lens record field -> field -> record -> record forall field record. Num field => Lens record field -> field -> record -> record -~ field f) --------------------------------------------------------------------------------- -- | Smart constructor @lens@ function. Used to easily construct a @Lens@ -- -- > name :: Lens Person String -- > name = lens _name $ \p n -> p { _name = n } -- lens :: (record -> field) -> (record -> field -> record) -> Lens record field lens :: forall record field. (record -> field) -> (record -> field -> record) -> Lens record field lens = (record -> field) -> (record -> field -> record) -> Lens record field forall record field. (record -> field) -> (record -> field -> record) -> Lens record field Lens ----------------------------------------------------------------------------