Skip to content

Instantly share code, notes, and snippets.

@jonsterling
Created September 23, 2015 17:29
Show Gist options
  • Save jonsterling/21dc46bc4dff553878ea to your computer and use it in GitHub Desktop.
Save jonsterling/21dc46bc4dff553878ea to your computer and use it in GitHub Desktop.
Reformulate Data.Injector in terms of profunctors for prism compatibility
From 9883e42e7f6f281e7ebada6d998d5a15789c6d6d Mon Sep 17 00:00:00 2001
From: Jonathan Sterling <jon@jonmsterling.com>
Date: Wed, 23 Sep 2015 10:28:12 -0700
Subject: [PATCH 1/1] Reformulate Injector in terms of profunctors
---
bower.json | 2 ++
docs/Data/Injector.md | 15 ++++++-----
src/Data/Injector.purs | 72 ++++++++++++++++++++++++++++++++++++++++----------
3 files changed, 69 insertions(+), 20 deletions(-)
diff --git a/bower.json b/bower.json
index e2022d0..6848d82 100644
--- a/bower.json
+++ b/bower.json
@@ -25,8 +25,10 @@
"purescript-dom": "^0.2.6",
"purescript-foreign": "^0.7.0",
"purescript-free": "^0.9.0",
+ "purescript-identity": "^0.4.0",
"purescript-maps": "^0.5.0",
"purescript-nullable": "^0.2.0",
+ "purescript-profunctor": "^0.3.1",
"purescript-unsafe-coerce": "^0.1.0",
"purescript-void": "^0.3.0"
}
diff --git a/docs/Data/Injector.md b/docs/Data/Injector.md
index ec102c8..1a78040 100644
--- a/docs/Data/Injector.md
+++ b/docs/Data/Injector.md
@@ -1,18 +1,21 @@
## Module Data.Injector
-#### `Injector`
+#### `Prism`
``` purescript
-data Injector a b
- = Injector (a -> b) (b -> Maybe a)
+type Prism s t a b = forall p f. (Choice p, Applicative f) => p a (f b) -> p s (f t)
```
-##### Instances
+Compatible with `Prism` from `purescript-lens`.
+
+#### `Injector`
+
``` purescript
-instance semigroupoidInjector :: Semigroupoid Injector
-instance categoryInjector :: Category Injector
+type Injector s a = Prism a a s s
```
+Compatible with `PrismP` from `purescript-lens`.
+
#### `inj`
``` purescript
diff --git a/src/Data/Injector.purs b/src/Data/Injector.purs
index 80b451a..0ee73a6 100644
--- a/src/Data/Injector.purs
+++ b/src/Data/Injector.purs
@@ -1,35 +1,79 @@
-module Data.Injector where
+module Data.Injector
+ ( Prism()
+ , Injector()
+ , inj
+ , prj
+ , injLE
+ , injLC
+ , injRE
+ , injRC
+ ) where
-import Prelude (Semigroupoid, Category, (<<<), const, id)
+import Prelude (Semigroup, Semigroupoid, Applicative, Category, (<<<), const, pure, map)
import Control.Bind ((<=<))
+import Data.Const
import Data.Either (Either(..), either)
import Data.Functor.Coproduct (Coproduct(), coproduct, left, right)
-import Data.Maybe (Maybe(..))
+import Data.Identity
+import Data.Maybe (Maybe(..), maybe)
+import Data.Monoid
+import qualified Data.Profunctor as PF
+import qualified Data.Profunctor.Choice as PF
-data Injector a b = Injector (a -> b) (b -> Maybe a)
+import Unsafe.Coerce
-instance semigroupoidInjector :: Semigroupoid Injector where
- compose (Injector injA prjA) (Injector injB prjB) = Injector (injA <<< injB) (prjB <=< prjA)
+-- | Compatible with `Prism` from `purescript-lens`.
+type Prism s t a b = forall p f. (PF.Choice p, Applicative f) => p a (f b) -> p s (f t)
-instance categoryInjector :: Category Injector where
- id = Injector id Just
+-- | Compatible with `PrismP` from `purescript-lens`.
+type Injector s a = Prism a a s s
+
+newtype Tagged s b = Tagged b
+
+instance profunctorTagged :: PF.Profunctor Tagged where
+ dimap _ f (Tagged b) = Tagged (f b)
+
+instance choiceTagged :: PF.Choice Tagged where
+ left (Tagged b) = Tagged (Left b)
+ right (Tagged b) = Tagged (Right b)
+
+newtype First a = First (Maybe a)
+
+getFirst :: forall a. First a -> Maybe a
+getFirst (First a) = a
+
+instance firstSemigroup :: Semigroup (First a) where
+ append (First Nothing) y = y
+ append x _ = x
+
+instance firstMonoid :: Monoid (First a) where
+ mempty = First Nothing
+
+unTagged :: forall s b. Tagged s b -> b
+unTagged (Tagged b) = b
inj :: forall a b. Injector a b -> a -> b
-inj (Injector f _) = f
+inj p = runIdentity <<< unTagged <<< p <<< Tagged <<< Identity
prj :: forall a b. Injector a b -> b -> Maybe a
-prj (Injector _ g) = g
+prj p = getFirst <<< getConst <<< p (Const <<< First <<< Just)
+
+prism :: forall s t a b. (b -> t) -> (s -> Either t a) -> Prism s t a b
+prism f g = PF.dimap g (either pure (map f)) <<< PF.right
+
+prism' :: forall s a b. (b -> s) -> (s -> Maybe a) -> Prism s s a b
+prism' f g = prism f (\s -> maybe (Left s) Right (g s))
injLE :: forall a b. Injector a (Either a b)
-injLE = Injector Left (either Just (const Nothing))
+injLE = prism' Left (either Just (const Nothing))
injRE :: forall a b. Injector a (Either b a)
-injRE = Injector Right (either (const Nothing) Just)
+injRE = prism' Right (either (const Nothing) Just)
injLC :: forall f g a. Injector (f a) (Coproduct f g a)
-injLC = Injector left (coproduct Just (const Nothing))
+injLC = prism' left (coproduct Just (const Nothing))
injRC :: forall f g a. Injector (f a) (Coproduct g f a)
-injRC = Injector right (coproduct (const Nothing) Just)
+injRC = prism' right (coproduct (const Nothing) Just)
--
2.1.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment