src: Lets: StoreLens: Implement store lens

Signed-off-by: Sanchayan Maity <maitysanchayan@gmail.com>
This commit is contained in:
Sanchayan Maity 2019-02-13 16:33:25 +05:30
parent 5186970bb8
commit 246f6b1302

View file

@ -47,12 +47,12 @@ module Lets.StoreLens (
) where ) where
import Control.Applicative(Applicative((<*>))) import Control.Applicative(Applicative((<*>)))
import Data.Char(toUpper) import Data.Char(toUpper, ord)
import Data.Functor((<$>)) import Data.Functor((<$>))
import Data.Map(Map) import Data.Map(Map)
import qualified Data.Map as Map(insert, delete, lookup) import qualified Data.Map as Map(insert, delete, lookup, fromList)
import Data.Set(Set) import Data.Set(Set)
import qualified Data.Set as Set(insert, delete, member) import qualified Data.Set as Set(insert, delete, member, fromList)
import Lets.Data(Store(Store), Person(Person), Locality(Locality), Address(Address)) import Lets.Data(Store(Store), Person(Person), Locality(Locality), Address(Address))
import Prelude hiding (product) import Prelude hiding (product)
@ -80,27 +80,23 @@ mapS ::
(a -> b) (a -> b)
-> Store s a -> Store s a
-> Store s b -> Store s b
mapS = mapS f (Store sToa s) = Store (\ss -> f (sToa ss)) s
error "todo: mapS"
duplicateS :: duplicateS ::
Store s a Store s a
-> Store s (Store s a) -> Store s (Store s a)
duplicateS = duplicateS (Store sToa a) = Store (\s -> Store sToa s) a
error "todo: duplicateS"
extendS :: extendS ::
(Store s a -> b) (Store s a -> b)
-> Store s a -> Store s a
-> Store s b -> Store s b
extendS = extendS f = mapS f . duplicateS
error "todo: extendS"
extractS :: extractS ::
Store s a Store s a
-> a -> a
extractS = extractS = \(Store sToa s) -> sToa s
error "todo: extractS"
---- ----
@ -193,8 +189,7 @@ modify ::
-> (b -> b) -> (b -> b)
-> a -> a
-> a -> a
modify = modify (Lens f) bTob a = let Store s g = f a in s (bTob g)
error "todo: modify"
-- | An alias for @modify@. -- | An alias for @modify@.
(%~) :: (%~) ::
@ -223,8 +218,7 @@ infixr 4 %~
-> b -> b
-> a -> a
-> a -> a
(.~) = (.~) = \(Lens f) -> \v -> \a -> let Store s g = f a in s v
error "todo: (.~)"
infixl 5 .~ infixl 5 .~
@ -244,9 +238,8 @@ fmodify ::
-> (b -> f b) -> (b -> f b)
-> a -> a
-> f a -> f a
fmodify = fmodify (Lens f) bTofb a = let Store s g = f a in s <$> bTofb g
error "todo: fmodify"
-- | -- |
-- --
-- >>> fstL |= Just 3 $ (7, "abc") -- >>> fstL |= Just 3 $ (7, "abc")
@ -260,8 +253,7 @@ fmodify =
-> f b -> f b
-> a -> a
-> f a -> f a
(|=) = (|=) (Lens f) fb a = let Store s g = f a in s <$> fb
error "todo: (|=)"
infixl 5 |= infixl 5 |=
@ -277,8 +269,7 @@ infixl 5 |=
-- prop> let types = (x :: Int, y :: String) in setsetLaw fstL (x, y) z -- prop> let types = (x :: Int, y :: String) in setsetLaw fstL (x, y) z
fstL :: fstL ::
Lens (x, y) x Lens (x, y) x
fstL = fstL = Lens (\(x, y) -> Store (\x' -> (x', y)) x)
error "todo: fstL"
-- | -- |
-- --
@ -292,8 +283,7 @@ fstL =
-- prop> let types = (x :: Int, y :: String) in setsetLaw sndL (x, y) z -- prop> let types = (x :: Int, y :: String) in setsetLaw sndL (x, y) z
sndL :: sndL ::
Lens (x, y) y Lens (x, y) y
sndL = sndL = Lens (\(x, y) -> Store (\y' -> (x, y')) y)
error "todo: sndL"
-- | -- |
-- --
@ -318,8 +308,10 @@ mapL ::
Ord k => Ord k =>
k k
-> Lens (Map k v) (Maybe v) -> Lens (Map k v) (Maybe v)
mapL = mapL k = Lens (\mkv -> Store (\mv -> case mv of
error "todo: mapL" Nothing -> Map.delete k mkv
Just a -> Map.insert k a mkv)
(Map.lookup k mkv))
-- | -- |
-- --
@ -344,8 +336,10 @@ setL ::
Ord k => Ord k =>
k k
-> Lens (Set k) Bool -> Lens (Set k) Bool
setL = setL k = Lens (\sk -> Store (\bool -> case bool of
error "todo: setL" True -> Set.insert k sk
False -> Set.delete k sk)
(Set.member k sk))
-- | -- |
-- --
@ -358,8 +352,10 @@ compose ::
Lens b c Lens b c
-> Lens a b -> Lens a b
-> Lens a c -> Lens a c
compose = compose = \(Lens f) -> \(Lens g) ->
error "todo: compose" Lens (\a -> let Store bToa b = g a
in let Store cTob c = f b
in Store (bToa . cTob) c)
-- | An alias for @compose@. -- | An alias for @compose@.
(|.) :: (|.) ::
@ -380,9 +376,8 @@ infixr 9 |.
-- 4 -- 4
identity :: identity ::
Lens a a Lens a a
identity = identity = Lens (\a -> Store (\a' -> a') a)
error "todo: identity"
-- | -- |
-- --
-- >>> get (product fstL sndL) (("abc", 3), (4, "def")) -- >>> get (product fstL sndL) (("abc", 3), (4, "def"))
@ -394,8 +389,10 @@ product ::
Lens a b Lens a b
-> Lens c d -> Lens c d
-> Lens (a, c) (b, d) -> Lens (a, c) (b, d)
product = product (Lens f) (Lens g) =
error "todo: product" Lens (\(a, c) -> let Store h i = f a
in let Store j k = g c
in Store (\(b, d) -> (h b, j d)) (i, k))
-- | An alias for @product@. -- | An alias for @product@.
(***) :: (***) ::
@ -424,8 +421,10 @@ choice ::
Lens a x Lens a x
-> Lens b x -> Lens b x
-> Lens (Either a b) x -> Lens (Either a b) x
choice = choice (Lens ax) (Lens bx) =
error "todo: choice" Lens (\eab -> case eab of
Left a -> let Store f g = ax a in Store (\x -> Left $ f x) g
Right b -> let Store h i = bx b in Store (\x -> Right $ h x) i)
-- | An alias for @choice@. -- | An alias for @choice@.
(|||) :: (|||) ::
@ -512,8 +511,7 @@ addressL =
getSuburb :: getSuburb ::
Person Person
-> String -> String
getSuburb = getSuburb = get $ (compose suburbL addressL)
error "todo: getSuburb"
-- | -- |
-- --
@ -526,8 +524,7 @@ setStreet ::
Person Person
-> String -> String
-> Person -> Person
setStreet = setStreet = set $ (compose streetL addressL)
error "todo: setStreet"
-- | -- |
-- --
@ -539,8 +536,9 @@ setStreet =
getAgeAndCountry :: getAgeAndCountry ::
(Person, Locality) (Person, Locality)
-> (Int, String) -> (Int, String)
getAgeAndCountry = getAgeAndCountry (person, locality) = (get ageL person,
error "todo: getAgeAndCountry" get countryL locality)
-- | -- |
-- --
@ -551,9 +549,11 @@ getAgeAndCountry =
-- (Person 28 "Mary" (Address "83 Mary Ln" "Maryland" (Locality "Some Other City" "Western Mary" "Maristan")),Address "15 Fred St" "Fredville" (Locality "Mary Mary" "Western Mary" "Maristan")) -- (Person 28 "Mary" (Address "83 Mary Ln" "Maryland" (Locality "Some Other City" "Western Mary" "Maristan")),Address "15 Fred St" "Fredville" (Locality "Mary Mary" "Western Mary" "Maristan"))
setCityAndLocality :: setCityAndLocality ::
(Person, Address) -> (String, Locality) -> (Person, Address) (Person, Address) -> (String, Locality) -> (Person, Address)
setCityAndLocality = setCityAndLocality (person, address) (city, locality) =
error "todo: setCityAndLocality" (set (cityL |. localityL |. addressL) person city,
set localityL address locality)
-- | -- |
-- --
-- >>> getSuburbOrCity (Left maryAddress) -- >>> getSuburbOrCity (Left maryAddress)
@ -564,8 +564,10 @@ setCityAndLocality =
getSuburbOrCity :: getSuburbOrCity ::
Either Address Locality Either Address Locality
-> String -> String
getSuburbOrCity = getSuburbOrCity = \soc -> case soc of
error "todo: getSuburbOrCity" Left address -> get suburbL address
Right locality -> get cityL locality
-- | -- |
-- --
@ -578,8 +580,9 @@ setStreetOrState ::
Either Person Locality Either Person Locality
-> String -> String
-> Either Person Locality -> Either Person Locality
setStreetOrState = setStreetOrState = \sos -> \ipsos -> case sos of
error "todo: setStreetOrState" Left person -> Left $ set (streetL |. addressL) person ipsos
Right locality -> Right $ set stateL locality ipsos
-- | -- |
-- --
@ -591,5 +594,4 @@ setStreetOrState =
modifyCityUppercase :: modifyCityUppercase ::
Person Person
-> Person -> Person
modifyCityUppercase = modifyCityUppercase = (cityL |. localityL |. addressL) %~ map toUpper
error "todo: modifyCityUppercase"