Skip to content

Commit df3b82b

Browse files
committed
Add Crosswalk instances for: NonEmpty, Proxy, Const, Functor.Sum, MaybeT, These1
1 parent d39a29a commit df3b82b

File tree

2 files changed

+77
-17
lines changed

2 files changed

+77
-17
lines changed

semialign/src/Data/Crosswalk.hs

Lines changed: 61 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
11
{-# LANGUAGE Trustworthy #-}
2+
{-# LANGUAGE DeriveFunctor #-}
23
module Data.Crosswalk (
34
-- * Crosswalk
45
Crosswalk (..),
56
-- * Bicrosswalk
67
Bicrosswalk (..),
78
) where
89

9-
import Control.Applicative (pure, (<$>))
10-
import Data.Bifoldable (Bifoldable (..))
11-
import Data.Bifunctor (Bifunctor (..))
12-
import Data.Foldable (Foldable (..))
13-
import Data.Functor.Compose (Compose (..))
14-
import Data.Functor.Identity (Identity (..))
15-
import Data.Vector.Generic (Vector)
16-
import Prelude (Either (..), Functor (fmap), Maybe (..), id, (.))
17-
10+
import Control.Applicative (Applicative (pure, (<*>)), (<$>), Const(..))
11+
import Control.Monad.Trans.Maybe (MaybeT (..))
12+
import Data.Bifoldable (Bifoldable (..))
13+
import Data.Bifunctor (Bifunctor (..))
14+
import Data.Foldable (Foldable (..))
15+
import Data.Functor.Compose (Compose (..))
16+
import Data.Functor.Identity (Identity (..))
17+
import Data.Functor.Sum (Sum (..))
18+
import Data.Functor.These (These1 (..))
19+
import Data.Proxy (Proxy (..))
20+
import Data.Traversable (Traversable (traverse))
21+
import Data.Vector.Generic (Vector)
22+
import Prelude (Either (..), Functor (fmap), Maybe (..), id, (.), uncurry, maybe)
23+
24+
import qualified Data.List.NonEmpty as NE
1825
import qualified Data.Sequence as Seq
1926
import qualified Data.Vector as V
2027
import qualified Data.Vector.Generic as VG
@@ -55,15 +62,15 @@ instance Crosswalk [] where
5562
crosswalk f (x:xs) = alignWith cons (f x) (crosswalk f xs)
5663
where cons = these pure id (:)
5764

65+
instance Crosswalk NE.NonEmpty where
66+
crosswalk f (x NE.:| []) = (NE.:| []) <$> f x
67+
crosswalk f (x1 NE.:| x2 : xs) = alignWith cons (f x1) (crosswalk f (x2 NE.:| xs))
68+
where cons = these (NE.:| []) id (NE.<|)
69+
5870
instance Crosswalk Seq.Seq where
5971
crosswalk f = foldr (alignWith cons . f) nil where
6072
cons = these Seq.singleton id (Seq.<|)
6173

62-
instance Crosswalk (These a) where
63-
crosswalk _ (This _) = nil
64-
crosswalk f (That x) = That <$> f x
65-
crosswalk f (These a x) = These a <$> f x
66-
6774
crosswalkVector :: (Vector v a, Vector v b, Align f)
6875
=> (a -> f b) -> v a -> f (v b)
6976
crosswalkVector f = fmap VG.fromList . VG.foldr (alignWith cons . f) nil where
@@ -72,18 +79,55 @@ crosswalkVector f = fmap VG.fromList . VG.foldr (alignWith cons . f) nil where
7279
instance Crosswalk V.Vector where
7380
crosswalk = crosswalkVector
7481

82+
instance Crosswalk (Either e) where
83+
crosswalk _ (Left _) = nil
84+
crosswalk f (Right x) = Right <$> f x
85+
86+
instance Crosswalk (These a) where
87+
crosswalk _ (This _) = nil
88+
crosswalk f (That x) = That <$> f x
89+
crosswalk f (These a x) = These a <$> f x
90+
7591
instance Crosswalk ((,) a) where
7692
crosswalk fun (a, x) = fmap ((,) a) (fun x)
7793

7894
-- can't (shouldn't) do longer tuples until there are Functor and Foldable
7995
-- instances for them
8096

97+
instance Crosswalk Proxy where
98+
crosswalk _ _ = nil
99+
100+
instance Crosswalk (Const r) where
101+
crosswalk _ _ = nil
102+
103+
instance (Crosswalk f, Crosswalk g) => Crosswalk (Sum f g) where
104+
crosswalk f (InL xs) = InL <$> crosswalk f xs
105+
crosswalk f (InR xs) = InR <$> crosswalk f xs
106+
107+
instance (Crosswalk f, Crosswalk g) => Crosswalk (These1 f g) where
108+
crosswalk f (This1 xs) = This1 <$> crosswalk f xs
109+
crosswalk f (That1 ys) = That1 <$> crosswalk f ys
110+
crosswalk f (These1 xs ys) = alignWith go (crosswalk f xs) (crosswalk f ys)
111+
where go = these This1 That1 These1
112+
81113
instance (Crosswalk f, Crosswalk g) => Crosswalk (Compose f g) where
82114
crosswalk f
83115
= fmap Compose -- can't coerce: maybe the Align-able thing has role nominal
84116
. crosswalk (crosswalk f)
85117
. getCompose
86118

119+
data Fill f a = Fill a (f a)
120+
deriving (Functor)
121+
122+
instance Align f => Applicative (Fill f) where
123+
pure x = Fill x nil
124+
Fill deff fs <*> Fill defx xs
125+
= Fill (deff defx) (alignWith (uncurry id . fromThese deff defx) fs xs)
126+
127+
instance Traversable t => Crosswalk (MaybeT t) where
128+
crosswalk f (MaybeT xs) = case traverse go xs of Fill _ ys -> MaybeT <$> ys
129+
where go mx = Fill Nothing (Just <$> maybe nil f mx)
130+
87131
-- --------------------------------------------------------------------------
88132
-- | Bifoldable bifunctors supporting traversal through an alignable
89133
-- functor.
@@ -113,3 +157,6 @@ instance Bicrosswalk These where
113157
bicrosswalk f _ (This x) = This <$> f x
114158
bicrosswalk _ g (That x) = That <$> g x
115159
bicrosswalk f g (These x y) = align (f x) (g y)
160+
161+
instance Bicrosswalk Const where
162+
bicrosswalk f _ (Const x) = Const <$> f x

these-tests/test/Tests/Crosswalk.hs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,16 @@
33
{-# LANGUAGE ScopedTypeVariables #-}
44
module Tests.Crosswalk (crosswalkProps) where
55

6+
import Control.Applicative (Const)
67
import Control.Monad.Trans.Instances ()
8+
import Control.Monad.Trans.Maybe (MaybeT)
79
import Data.Functor.Compose (Compose (..))
810
import Data.Functor.Identity (Identity (..))
11+
import Data.Functor.Sum (Sum)
12+
import Data.Functor.These (These1)
13+
import Data.List.NonEmpty (NonEmpty)
914
import Data.Map (Map)
15+
import Data.Proxy (Proxy)
1016
import Data.Semigroup (Semigroup (..))
1117
import Data.Sequence (Seq)
1218
import Data.Typeable (Typeable, typeOf1)
@@ -27,14 +33,21 @@ import Tests.Orphans ()
2733

2834
crosswalkProps :: TestTree
2935
crosswalkProps = testGroup "Crosswalk"
30-
[ crosswalkLaws (P :: P [])
36+
[ crosswalkLaws (P :: P Identity)
3137
, crosswalkLaws (P :: P Maybe)
32-
, crosswalkLaws (P :: P Identity)
33-
, crosswalkLaws (P :: P (These Int))
38+
, crosswalkLaws (P :: P [])
39+
, crosswalkLaws (P :: P NonEmpty)
3440
, crosswalkLaws (P :: P Seq)
3541
, crosswalkLaws (P :: P V.Vector)
42+
, crosswalkLaws (P :: P (Either Int))
43+
, crosswalkLaws (P :: P (These Int))
3644
, crosswalkLaws (P :: P ((,) Int))
45+
, crosswalkLaws (P :: P Proxy)
46+
, crosswalkLaws (P :: P (Const Int))
47+
, crosswalkLaws (P :: P (Sum [] []))
48+
, crosswalkLaws (P :: P (These1 [] []))
3749
, crosswalkLaws (P :: P (Compose [] []))
50+
, crosswalkLaws (P :: P (MaybeT []))
3851
]
3952

4053
-------------------------------------------------------------------------------

0 commit comments

Comments
 (0)