Skip to content

Commit 361ca29

Browse files
committed
Some rudimentary interaction with state monads.
1 parent e6b0fab commit 361ca29

File tree

6 files changed

+118
-3
lines changed

6 files changed

+118
-3
lines changed

bower.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"purescript-maps": "~0.5.2",
2323
"purescript-profunctor": "~0.3.0",
2424
"purescript-sets": "~0.5.1",
25-
"purescript-unsafe-coerce": "~0.1.0"
25+
"purescript-unsafe-coerce": "~0.1.0",
26+
"purescript-transformers": "~0.7.1"
2627
}
2728
}

src/Data/Lens/Getter.purs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
module Data.Lens.Getter
44
( (^.)
5-
, view, to
5+
, view, to, use
66
, module Data.Lens.Types
77
) where
88

@@ -11,6 +11,7 @@ import Prelude ((<<<))
1111
import Data.Const (Const(..), getConst)
1212
import Data.Functor.Contravariant (Contravariant, cmap)
1313
import Data.Profunctor.Star (Star(..), runStar)
14+
import Control.Monad.State.Class (MonadState, gets)
1415

1516
import Data.Lens.Types (Getter(), Optic())
1617

@@ -27,3 +28,6 @@ view l s = getConst (runStar (l (Star Const)) s)
2728
-- | Convert a function into a getter.
2829
to :: forall s a f. (Contravariant f) => (s -> a) -> Optic (Star f) s s a a
2930
to f p = Star (cmap f <<< runStar p <<< f)
31+
32+
use :: forall s t a b m. (MonadState s m) => Getter s t a b -> m a
33+
use p = gets (^. p)

src/Data/Lens/Internal/Focusing.purs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
-- | This module defines the `Focusing` functor
2+
3+
module Data.Lens.Internal.Focusing
4+
( Focusing (..)
5+
, runFocusing
6+
) where
7+
8+
import Prelude
9+
import Data.Monoid (Monoid)
10+
import Data.Tuple (Tuple ())
11+
12+
-- | The functor used to zoom into `StateT`.
13+
newtype Focusing m s a = Focusing (m (Tuple s a))
14+
15+
runFocusing :: forall m s a. Focusing m s a -> m (Tuple s a)
16+
runFocusing (Focusing r) = r
17+
18+
instance focusingFunctor :: (Functor m) => Functor (Focusing m s) where
19+
map f (Focusing r) = Focusing (map (map f) r)
20+
21+
instance focusingApply :: (Apply m, Semigroup s) => Apply (Focusing m s) where
22+
apply (Focusing rf) (Focusing rx) = Focusing (map (<*>) rf <*> rx)
23+
24+
instance focusingApplicative :: (Applicative m, Monoid s) => Applicative (Focusing m s) where
25+
pure = Focusing <<< pure <<< pure

src/Data/Lens/Setter.purs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22

33
module Data.Lens.Setter
44
( (%~), (.~), (+~), (-~), (*~), (//~), (||~), (&&~), (<>~), (++~), (?~)
5+
, (.=), (%=), (+=), (*=), (-=), (//=), (||=), (&&=), (<>=), (++=), (?=)
56
, over, set
67
, module Data.Lens.Types
78
) where
89

910
import Prelude
1011

12+
import Control.Monad.State.Class (MonadState, modify)
1113
import Data.Maybe (Maybe(..))
1214

1315
import Data.Lens.Types (Setter(), SetterP())
@@ -24,6 +26,18 @@ infixr 4 <>~
2426
infixr 4 ++~
2527
infixr 4 ?~
2628

29+
infix 4 .=
30+
infix 4 %=
31+
infix 4 +=
32+
infix 4 *=
33+
infix 4 -=
34+
infix 4 //=
35+
infix 4 ||=
36+
infix 4 &&=
37+
infix 4 <>=
38+
infix 4 ++=
39+
infix 4 ?=
40+
2741
-- | Apply a function to the foci of a `Setter`.
2842
over :: forall s t a b. Setter s t a b -> (a -> b) -> s -> t
2943
over l = l
@@ -66,3 +80,48 @@ set l b = over l (const b)
6680

6781
(?~) :: forall s t a b. Setter s t a (Maybe b) -> b -> s -> t
6882
(?~) p = set p <<< Just
83+
84+
-- Stateful
85+
86+
-- | Set the foci of a `Setter` in a monadic state to a constant value.
87+
assign :: forall s a b m. (MonadState s m) => Setter s s a b -> b -> m Unit
88+
assign p b = modify (set p b)
89+
90+
-- | Modify the foci of a `Setter` in a monadic state.
91+
modifying :: forall s a b m. (MonadState s m) => Setter s s a b -> (a -> b) -> m Unit
92+
modifying p f = modify (over p f)
93+
94+
-- | Synonym for `assign`
95+
(.=) :: forall s a b m. (MonadState s m) => Setter s s a b -> b -> m Unit
96+
(.=) = assign
97+
98+
-- | Synonym for `modifying`
99+
(%=) :: forall s a b m. (MonadState s m) => Setter s s a b -> (a -> b) -> m Unit
100+
(%=) = modifying
101+
102+
(+=) :: forall s a m. (MonadState s m, Semiring a) => SetterP s a -> a -> m Unit
103+
(+=) p = modifying p <<< add
104+
105+
(*=) :: forall s a m. (MonadState s m, Semiring a) => SetterP s a -> a -> m Unit
106+
(*=) p = modifying p <<< flip mul
107+
108+
(-=) :: forall s a m. (MonadState s m, Ring a) => SetterP s a -> a -> m Unit
109+
(-=) p = modifying p <<< flip sub
110+
111+
(//=) :: forall s a m. (MonadState s m, DivisionRing a) => SetterP s a -> a -> m Unit
112+
(//=) p = modifying p <<< flip div
113+
114+
(||=) :: forall s a m. (MonadState s m, BooleanAlgebra a) => SetterP s a -> a -> m Unit
115+
(||=) p = modifying p <<< flip disj
116+
117+
(&&=) :: forall s a m. (MonadState s m, BooleanAlgebra a) => SetterP s a -> a -> m Unit
118+
(&&=) p = modifying p <<< flip conj
119+
120+
(<>=) :: forall s a m. (MonadState s m, Semigroup a) => SetterP s a -> a -> m Unit
121+
(<>=) p = modifying p <<< flip append
122+
123+
(++=) :: forall s a m. (MonadState s m, Semigroup a) => SetterP s a -> a -> m Unit
124+
(++=) p = modifying p <<< flip append
125+
126+
(?=) :: forall s a b m. (MonadState s m) => Setter s s a (Maybe b) -> b -> m Unit
127+
(?=) p = assign p <<< Just

src/Data/Lens/Zoom.purs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
-- | This module defines functions for zooming in a state monad.
2+
3+
module Data.Lens.Zoom
4+
( zoom
5+
, module Data.Lens.Types
6+
) where
7+
8+
import Prelude
9+
10+
import Control.Monad.State.Trans (StateT (..), runStateT)
11+
import Data.Profunctor.Star (Star (..), runStar)
12+
13+
import Data.Lens.Types
14+
import Data.Lens.Internal.Focusing (Focusing (..), runFocusing)
15+
16+
-- | Zooms into a substate in a `StateT` transformer.
17+
zoom :: forall a s r m. OpticP (Star (Focusing m r)) s a -> StateT a m r -> StateT s m r
18+
zoom p ma = StateT $ runFocusing <<< runStar (p $ Star $ Focusing <<< runStateT ma)

test/Main.purs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ import Prelude
55
import Data.Maybe
66
import Data.Either
77
import Data.Lens
8+
import Data.Lens.Zoom
89
import Data.Tuple
910
import Data.Traversable (Traversable)
1011

1112
import Control.Monad.Eff.Console
13+
import Control.Monad.State
1214

1315
foo :: forall a b r. Lens { foo :: a | r } { foo :: b | r } a b
1416
foo = lens _.foo (_ { foo = _ })
@@ -24,4 +26,10 @@ doc = { foo: Just { bar: [ "Hello", " ", "World" ]} }
2426
bars :: forall a b. Traversal (Foo a) (Foo b) a b
2527
bars = foo <<< _Just <<< bar <<< traversed
2628

27-
main = print $ view bars doc
29+
stateTest :: Tuple Int String
30+
stateTest = evalState go (Tuple 4 ["Foo", "Bar"]) where
31+
go = Tuple <$> zoom _1 get <*> zoom (_2 <<< traversed) get
32+
33+
main = do
34+
print $ view bars doc
35+
print stateTest

0 commit comments

Comments
 (0)