0 | module Control.Lens.Prism
2 | import Data.Profunctor
3 | import Control.Lens.Optic
4 | import Control.Lens.Indexed
5 | import Control.Lens.Iso
16 | record IsPrism p where
17 | constructor MkIsPrism
18 | runIsPrism : Choice p
21 | prismToIso : IsPrism p => IsIso p
22 | prismToIso @{MkIsPrism _} = MkIsIso %search
25 | indexedPrism : IsPrism p => IsPrism (Indexed i p)
26 | indexedPrism @{MkIsPrism _} = MkIsPrism %search
36 | 0 Prism : (s,t,a,b : Type) -> Type
37 | Prism = Optic IsPrism
41 | 0 Prism' : (s,a : Type) -> Type
42 | Prism' = Simple Prism
45 | 0 IndexedPrism : (i,s,t,a,b : Type) -> Type
46 | IndexedPrism = IndexedOptic IsPrism
49 | 0 IndexedPrism' : (i,s,a : Type) -> Type
50 | IndexedPrism' = Simple . IndexedPrism
60 | prism : (b -> t) -> (s -> Either t a) -> Prism s t a b
61 | prism inj prj @{MkIsPrism _} = dimap prj (either id inj) . right
65 | prism' : (b -> s) -> (s -> Maybe a) -> Prism s s a b
66 | prism' inj prj = prism inj (\x => maybe (Left x) Right (prj x))
69 | iprism : (b -> t) -> (s -> Either t (i, a)) -> IndexedPrism i s t a b
70 | iprism inj prj @{_} @{ind} = prism inj prj . indexed @{ind}
73 | iprism' : (b -> s) -> (s -> Maybe (i, a)) -> IndexedPrism i s s a b
74 | iprism' inj prj = iprism inj (\x => maybe (Left x) Right (prj x))
79 | getPrism : Prism s t a b -> (b -> t, s -> Either t a)
80 | getPrism l = l @{MkIsPrism choice} (id, Right)
82 | Profunctor (\x,y => (b -> y, x -> Either y a)) where
83 | dimap f g (inj, prj) = (g . inj, either (Left . g) Right . prj . f)
85 | [choice] GenStrong Either (\x,y => (b -> y, x -> Either y a)) where
86 | strongl (inj, prj) = (Left . inj, either (either (Left . Left) Right . prj) (Left . Right))
87 | strongr (inj, prj) = (Right . inj, either (Left . Left) (either (Left . Right) Right . prj))
91 | withPrism : Prism s t a b -> ((b -> t) -> (s -> Either t a) -> r) -> r
92 | withPrism l f = uncurry f (getPrism l)
97 | nearly : a -> (a -> Bool) -> Prism' a ()
98 | nearly x p = prism' (const x) (guard . p)
102 | only : Eq a => a -> Prism' a ()
103 | only x = nearly x (x ==)
110 | without : Prism s t a b -> Prism s' t' a' b' -> Prism (Either s s') (Either t t') (Either a a') (Either b b')
112 | let (inj1, prj1) = getPrism l
113 | (inj2, prj2) = getPrism l'
114 | in prism (bimap inj1 inj2) (either (bimap Left Left . prj1) (bimap Right Right . prj2))
121 | below : Traversable f => Prism' s a -> Prism' (f s) (f a)
122 | below l = withPrism l $
\inj,prj =>
123 | prism (map inj) $
\s => mapFst (const s) (traverse prj s)
127 | aside : Prism s t a b -> Prism (e, s) (e, t) (e, a) (e, b)
128 | aside l = withPrism l $
\inj,prj => prism (map inj) $
\(e,s) => bimap (e,) (e,) (prj s)