Skip to content

Commit ba11011

Browse files
authored
Add record lenses (#59)
* Add record lenses * Import fst, snd * Use Lens synonym * Update Record.purs
1 parent e8d48d2 commit ba11011

File tree

3 files changed

+72
-6
lines changed

3 files changed

+72
-6
lines changed

bower.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
"purescript-profunctor": "^3.0.0",
1919
"purescript-sets": "^3.0.0",
2020
"purescript-unsafe-coerce": "^3.0.0",
21-
"purescript-transformers": "^3.0.0"
21+
"purescript-transformers": "^3.0.0",
22+
"purescript-symbols": "^3.0.0"
2223
},
2324
"devDependencies": {
2425
"purescript-console": "^3.0.0"

src/Data/Lens/Record.purs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
module Data.Lens.Record (prop) where
2+
3+
import Prelude
4+
import Data.StrMap as S
5+
import Data.Lens (Lens, lens)
6+
import Data.Maybe (fromJust)
7+
import Data.Symbol (class IsSymbol, SProxy, reflectSymbol)
8+
import Partial.Unsafe (unsafePartial)
9+
import Unsafe.Coerce (unsafeCoerce)
10+
11+
unsafeGet
12+
:: forall r a
13+
. String
14+
-> Record r
15+
-> a
16+
unsafeGet s = unsafePartial fromJust <<< S.lookup s <<< unsafeCoerce
17+
18+
unsafeSet
19+
:: forall r1 r2 a
20+
. String
21+
-> a
22+
-> Record r1
23+
-> Record r2
24+
unsafeSet s a = unsafeCoerce <<< S.insert s a <<< unsafeCoerce
25+
26+
get
27+
:: forall r r' l a
28+
. IsSymbol l
29+
=> RowCons l a r' r
30+
=> SProxy l
31+
-> Record r
32+
-> a
33+
get l = unsafeGet (reflectSymbol l)
34+
35+
set
36+
:: forall r1 r2 r l a b
37+
. IsSymbol l
38+
=> RowCons l a r r1
39+
=> RowCons l b r r2
40+
=> SProxy l
41+
-> b
42+
-> Record r1
43+
-> Record r2
44+
set l = unsafeSet (reflectSymbol l)
45+
46+
-- | Construct a (type-changing) lens for a record property, by providing a
47+
-- | proxy for the `Symbol` which corresponds to the property label.
48+
-- |
49+
-- | The lens is polymorphic in the rest of the row of property labels.
50+
-- |
51+
-- | For example:
52+
-- |
53+
-- | ```purescript
54+
-- | prop (SProxy :: SProxy "foo")
55+
-- | :: forall a b r. Lens { foo :: a | r } { foo :: b | r } a b
56+
-- | ```
57+
prop
58+
:: forall l r1 r2 r a b
59+
. IsSymbol l
60+
=> RowCons l a r r1
61+
=> RowCons l b r r2
62+
=> SProxy l
63+
-> Lens (Record r1) (Record r2) a b
64+
prop l = lens (get l) (flip (set l))

test/Main.purs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,26 @@ import Control.Monad.Eff.Console (CONSOLE, logShow)
66
import Control.Monad.State (evalState, get)
77
import Data.Distributive (class Distributive)
88
import Data.Either (Either(..))
9-
import Data.Lens (_1, _2, _Just, _Left, collectOf, lens, traversed, view)
9+
import Data.Lens (view, traversed, _1, _2, _Just, _Left, lens, collectOf)
1010
import Data.Lens.Fold ((^?))
1111
import Data.Lens.Fold.Partial ((^?!), (^@?!))
12-
import Data.Lens.Grate (cloneGrate, grate, zipWithOf)
12+
import Data.Lens.Grate (Grate, cloneGrate, grate, zipWithOf)
1313
import Data.Lens.Index (ix)
1414
import Data.Lens.Lens (ilens, IndexedLens, cloneIndexedLens)
15+
import Data.Lens.Record (prop)
1516
import Data.Lens.Setter (iover)
16-
import Data.Lens.Types (Grate)
1717
import Data.Lens.Zoom (Traversal, Traversal', Lens, Lens', zoom)
1818
import Data.Maybe (Maybe(..))
19+
import Data.Symbol (SProxy(..))
1920
import Data.Tuple (Tuple(..), fst, snd)
2021
import Partial.Unsafe (unsafePartial)
2122

2223
-- Traversing an array nested within a record
2324
foo :: forall a b r. Lens { foo :: a | r } { foo :: b | r } a b
24-
foo = lens _.foo (_ { foo = _ })
25+
foo = prop (SProxy :: SProxy "foo")
2526

2627
bar :: forall a b r. Lens { bar :: a | r } { bar :: b | r } a b
27-
bar = lens _.bar (_ { bar = _ })
28+
bar = prop (SProxy :: SProxy "bar")
2829

2930
type Foo a = { foo :: Maybe { bar :: Array a } }
3031

0 commit comments

Comments
 (0)