Skip to content

Commit e8d48d2

Browse files
authored
Grates (#60)
1 parent e9330dc commit e8d48d2

File tree

6 files changed

+113
-12
lines changed

6 files changed

+113
-12
lines changed

src/Data/Lens.purs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@ module Data.Lens
1919
, module Data.Lens.Setter
2020
, module Data.Lens.Getter
2121
, module Data.Lens.Fold
22+
, module Data.Lens.Grate
2223
, module Data.Lens.Common
2324
) where
2425

2526
import Data.Lens.Iso (AnIso, AnIso', Iso, Iso', Optic, Exchange(..), Re(..), au, auf, cloneIso, non, curried, flipped, iso, re, uncurried, under, withIso)
27+
import Data.Lens.Grate (Grate, Grate', zipWithOf, zipFWithOf, collectOf)
2628
import Data.Lens.Lens (ALens, ALens', Lens, Lens', cloneLens, lens, lens', withLens)
2729
import Data.Lens.Prism (APrism, APrism', Prism, Prism', Review, Review', clonePrism, is, isn't, matching, nearly, only, prism, prism', review, withPrism)
2830
import Data.Lens.Traversal (Traversal, Traversal', element, elementsOf, failover, itraverseOf, sequenceOf, traverseOf, traversed)

src/Data/Lens/Grate.purs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
-- | This module defines functions for working with grates.
2+
-- |
3+
-- | See <http://r6research.livejournal.com/28050.html>.
4+
module Data.Lens.Grate
5+
( grate
6+
, withGrate
7+
, cloneGrate
8+
, cotraversed
9+
, zipWithOf
10+
, zipFWithOf
11+
, collectOf
12+
, module Data.Lens.Types
13+
) where
14+
15+
import Prelude
16+
import Data.Distributive (class Distributive, cotraverse)
17+
import Data.Lens.Internal.Grating (Grating(..))
18+
import Data.Lens.Internal.Zipping (Zipping(..))
19+
import Data.Lens.Types (Grate, Grate', Optic, AGrate)
20+
import Data.Newtype (unwrap)
21+
import Data.Profunctor (dimap)
22+
import Data.Profunctor.Closed (closed)
23+
import Data.Profunctor.Costar (Costar(..))
24+
import Data.Profunctor.Star (Star(..))
25+
26+
grate :: forall s t a b. (((s -> a) -> b) -> t) -> Grate s t a b
27+
grate f pab = dimap (#) f (closed pab)
28+
29+
withGrate :: forall s t a b. AGrate s t a b -> ((s -> a) -> b) -> t
30+
withGrate g = unwrap (g (Grating \f -> f id))
31+
32+
cloneGrate :: forall s t a b. AGrate s t a b -> Grate s t a b
33+
cloneGrate g = grate (withGrate g)
34+
35+
cotraversed :: forall f a b. Distributive f => Grate (f a) (f b) a b
36+
cotraversed = grate \f -> cotraverse f id
37+
38+
zipWithOf :: forall s t a b. Optic Zipping s t a b -> (a -> a -> b) -> s -> s -> t
39+
zipWithOf g f = unwrap (g (Zipping f))
40+
41+
zipFWithOf :: forall f s t a b. Optic (Costar f) s t a b -> (f a -> b) -> (f s -> t)
42+
zipFWithOf g f = unwrap (g (Costar f))
43+
44+
collectOf :: forall f s t a b. Optic (Star f) s t a b -> (a -> f b) -> s -> f t
45+
collectOf g f = unwrap (g (Star f))

src/Data/Lens/Internal/Grating.purs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module Data.Lens.Internal.Grating where
2+
3+
import Prelude
4+
import Data.Newtype (class Newtype)
5+
import Data.Profunctor (class Profunctor)
6+
import Data.Profunctor.Closed (class Closed)
7+
8+
newtype Grating a b s t = Grating (((s -> a) -> b) -> t)
9+
10+
derive instance newtypeGrating :: Newtype (Grating a b s t) _
11+
12+
instance profunctorGrating :: Profunctor (Grating a b) where
13+
dimap f g (Grating z) = Grating \d -> g (z \k -> d (k <<< f))
14+
15+
instance closedGrating :: Closed (Grating a b) where
16+
closed (Grating z) = Grating \f x -> z \k -> f \g -> k (g x)

src/Data/Lens/Internal/Zipping.purs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module Data.Lens.Internal.Zipping where
2+
3+
import Data.Newtype (class Newtype)
4+
import Data.Profunctor (class Profunctor)
5+
import Data.Profunctor.Closed (class Closed)
6+
7+
newtype Zipping a b = Zipping (a -> a -> b)
8+
9+
derive instance newtypeZipping :: Newtype (Zipping a b) _
10+
11+
instance profunctorZipping :: Profunctor Zipping where
12+
dimap f g (Zipping z) = Zipping \a1 a2 -> g (z (f a1) (f a2))
13+
14+
instance closedZipping :: Closed Zipping where
15+
closed (Zipping z) = Zipping \f1 f2 x -> z (f1 x) (f2 x)

src/Data/Lens/Types.purs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,16 @@ module Data.Lens.Types
66
, module Data.Lens.Internal.Shop
77
, module Data.Lens.Internal.Tagged
88
, module Data.Lens.Internal.Forget
9+
, module Data.Lens.Internal.Grating
910
, module Data.Lens.Internal.Wander
1011
, module Data.Lens.Internal.Re
1112
, module Data.Lens.Internal.Indexed
1213
) where
1314

15+
import Data.Tuple
1416
import Data.Lens.Internal.Exchange (Exchange(..))
1517
import Data.Lens.Internal.Forget (Forget(..))
18+
import Data.Lens.Internal.Grating (Grating)
1619
import Data.Lens.Internal.Indexed (Indexed(..))
1720
import Data.Lens.Internal.Market (Market(..))
1821
import Data.Lens.Internal.Re (Re(..))
@@ -21,8 +24,8 @@ import Data.Lens.Internal.Tagged (Tagged(..))
2124
import Data.Lens.Internal.Wander (class Wander, wander)
2225
import Data.Profunctor (class Profunctor)
2326
import Data.Profunctor.Choice (class Choice)
27+
import Data.Profunctor.Closed (class Closed)
2428
import Data.Profunctor.Strong (class Strong)
25-
import Data.Tuple
2629

2730
-- | A general-purpose Data.Lens.
2831
type Optic p s t a b = p a b -> p s t
@@ -60,6 +63,13 @@ type APrism' s a = APrism s s a a
6063
type Traversal s t a b = forall p. Wander p => Optic p s t a b
6164
type Traversal' s a = Traversal s s a a
6265

66+
-- | A grate (http://r6research.livejournal.com/28050.html)
67+
type Grate s t a b = forall p. Closed p => Optic p s t a b
68+
type Grate' s a = Grate s s a a
69+
70+
type AGrate s t a b = Optic (Grating a b) s t a b
71+
type AGrate' s a = AGrate s s a a
72+
6373
-- | A getter.
6474
type Getter s t a b = Fold a s t a b
6575
type Getter' s a = Getter s s a a

test/Main.purs

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
module Test.Main where
22

33
import Prelude
4-
5-
import Data.Lens (view, traversed, _1, _2, _Just, _Left, lens)
6-
import Data.Lens.Index (ix)
7-
import Data.Lens.Setter (iover)
8-
import Data.Lens.Lens (ilens, IndexedLens, cloneIndexedLens)
9-
import Data.Lens.Fold ((^?))
10-
import Data.Lens.Fold.Partial ((^?!), (^@?!))
11-
import Data.Lens.Zoom (Traversal, Traversal', Lens, Lens', zoom)
12-
import Data.Tuple (Tuple(..))
13-
import Data.Maybe (Maybe(..))
14-
import Data.Either (Either(..))
154
import Control.Monad.Eff (Eff)
165
import Control.Monad.Eff.Console (CONSOLE, logShow)
176
import Control.Monad.State (evalState, get)
7+
import Data.Distributive (class Distributive)
8+
import Data.Either (Either(..))
9+
import Data.Lens (_1, _2, _Just, _Left, collectOf, lens, traversed, view)
10+
import Data.Lens.Fold ((^?))
11+
import Data.Lens.Fold.Partial ((^?!), (^@?!))
12+
import Data.Lens.Grate (cloneGrate, grate, zipWithOf)
13+
import Data.Lens.Index (ix)
14+
import Data.Lens.Lens (ilens, IndexedLens, cloneIndexedLens)
15+
import Data.Lens.Setter (iover)
16+
import Data.Lens.Types (Grate)
17+
import Data.Lens.Zoom (Traversal, Traversal', Lens, Lens', zoom)
18+
import Data.Maybe (Maybe(..))
19+
import Data.Tuple (Tuple(..), fst, snd)
1820
import Partial.Unsafe (unsafePartial)
1921

2022
-- Traversing an array nested within a record
@@ -60,6 +62,16 @@ cloneTest = iover (cloneIndexedLens i_2) Tuple (Tuple 1 2)
6062
i_2 :: forall a b c. IndexedLens Int (Tuple a b) (Tuple a c) b c
6163
i_2 = ilens (\(Tuple _ b) -> Tuple 0 b) (\(Tuple a _) b -> Tuple a b)
6264

65+
-- Grates
66+
aGrateExample :: forall a b. Grate (Tuple a a) (Tuple b b) a b
67+
aGrateExample = grate \f -> Tuple (f fst) (f snd)
68+
69+
collectOfTest :: forall f a b. Distributive f => (a -> f b) -> Tuple a a -> f (Tuple b b)
70+
collectOfTest = collectOf aGrateExample
71+
72+
summing :: Tuple Int Int -> Tuple Int Int -> Tuple Int Int
73+
summing = zipWithOf (cloneGrate aGrateExample) (+)
74+
6375
main :: forall e. Eff (console :: CONSOLE | e) Unit
6476
main = do
6577
logShow $ view bars doc
@@ -68,3 +80,4 @@ main = do
6880
logShow $ unsafePartial $ Tuple 0 1 ^@?! i_2
6981
logShow stateTest
7082
logShow cloneTest
83+
logShow (summing (Tuple 1 2) (Tuple 3 4))

0 commit comments

Comments
 (0)