git.iko.soy/semi-iso-optics
on master help sign in
Added 'morphed' semi-iso and /$~, ~$/, ~$~ operators.
commitb978d852ed47c40560a4567837456061bc9a3e9d authorPaweł Nowak <pawel834@gmail.com> dateSun 23 Nov 2014, 01:09 (12 years ago) parent93dab1b
3 files changed+43−2
Control/Lens/SemiIso.hs+11 Data/SemiIsoFunctor.hs+30−1 semi-iso.cabal+2−1
Control/Lens/SemiIso.hs+11
@@ -1,3 +1,4 @@
1+{-# LANGUAGE TypeFamilies #-}
12{-# LANGUAGE Rank2Types #-}
23{-# LANGUAGE TupleSections #-}
34{-# LANGUAGE ViewPatterns #-}
@@ -58,6 +59,7 @@ module Control.Lens.SemiIso (
5859 unit,
5960 swapped,
6061 associated,
62+ morphed,
6163 constant,
6264 exact,
6365
@@ -99,6 +101,7 @@ import Data.Foldable
99101import Data.Functor.Identity
100102import Data.Profunctor.Exposed
101103import Data.Traversable
104+import Data.Tuple.Morph
102105
103106-- | A semi-isomorphism is a partial isomorphism with weakened laws.
104107--
@@ -157,6 +160,14 @@ unit = iso (, ()) fst
157160associated :: Iso' (a, (b, c)) ((a, b), c)
158161associated = iso (\(a, (b, c)) -> ((a, b), c)) (\((a, b), c) -> (a, (b, c)))
159162
163+-- | An isomorphism between two arbitrary nested tuples, as long the contained
164+-- types (ignoring units!) read from left to right are the same.
165+--
166+-- This is implemented using 'Data.Tuple.Morph.morph' from 'tuple-morph'.
167+morphed :: (HFoldable a, HUnfoldable a, HFoldable b, HUnfoldable b, Rep a ~ Rep b)
168+ => Iso' a b
169+morphed = iso morph morph
170+
160171-- | \-> Always returns the argument.
161172--
162173-- \<- Maps everything to a @()@.
Data/SemiIsoFunctor.hs+30−1
@@ -1,3 +1,5 @@
1+{-# LANGUAGE TypeFamilies #-}
2+{-# LANGUAGE PatternSynonyms #-}
13{- |
24Module : Data.SemiIsoFunctor
35Description : Functors from the category of semi-isomoprihsms to Hask.
@@ -18,10 +20,13 @@ module Data.SemiIsoFunctor where
1820
1921import Control.Lens.Cons
2022import Control.Lens.Empty
23+import Control.Lens.Internal.SemiIso
2124import Control.Lens.SemiIso
25+import Data.Functor.Identity
26+import Data.Tuple.Morph
2227
2328infixl 3 /|/
24−infixl 4 /$/
29+infixl 4 /$/, ~$/, /$~, ~$~
2530infixl 5 /*/, /*, */
2631infixl 1 //=
2732infixr 1 =//
@@ -54,6 +59,30 @@ class SemiIsoFunctor f where
5459(/$/) :: SemiIsoFunctor f => ASemiIso' a b -> f b -> f a
5560(/$/) = simap
5661
62+-- | @ai /$~ f@ is equal to @ai . morphed /$/ f@.
63+--
64+-- This operator handles all the hairy stuff with uncurried application:
65+-- it reassociates the argument tuple and removes unnecessary (or adds necessary)
66+-- units to match the function type. You don't have to use /* and */ with this
67+-- operator.
68+(/$~) :: (SemiIsoFunctor f, HFoldable b', HFoldable b,
69+ HUnfoldable b', HUnfoldable b, Rep b' ~ Rep b)
70+ => ASemiIso' a b' -> f b -> f a
71+(SemiIso f g) /$~ h = semiIso f g . morphed /$/ h
72+
73+-- | @ai ~$/ f@ is equal to @morphed . ai /$/ f@.
74+(~$/) :: (SemiIsoFunctor f, HFoldable a', HFoldable a,
75+ HUnfoldable a', HUnfoldable a, Rep a' ~ Rep a)
76+ => ASemiIso' a' b -> f b -> f a
77+(SemiIso f g) ~$/ h = morphed . semiIso f g /$/ h
78+
79+-- | @ai ~$~ f@ is equal to @morphed . ai . morphed /$/ f@.
80+(~$~) :: (SemiIsoFunctor f, HFoldable b', HFoldable b', HFoldable b,
81+ HFoldable a, HUnfoldable b', HUnfoldable b', HUnfoldable b,
82+ HUnfoldable a, Rep b' ~ Rep b, Rep b' ~ Rep a)
83+ => ASemiIso b' b' b' b' -> f b -> f a
84+(SemiIso f g) ~$~ h = morphed . semiIso f g . morphed /$/ h
85+
5786-- | Equivalent of 'Applicative' for 'SemiIsoFunctor'.
5887--
5988-- However, this class implements uncurried application, unlike
semi-iso.cabal+2−1
@@ -24,5 +24,6 @@ library
2424 Control.Lens.Internal.SemiIso
2525 Data.SemiIsoFunctor
2626 Data.Profunctor.Exposed
27− build-depends: base >= 4 && < 5, profunctors, transformers, lens
27+ build-depends: base >= 4 && < 5, profunctors, transformers, lens, tuple-morph
2828 default-language: Haskell2010
29+ ghc-options: -Wall