Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Crosswalk instances for: NonEmpty, Proxy, Const, Functor.Sum, These1 #193

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 39 additions & 6 deletions semialign/src/Data/Crosswalk.hs
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE DeriveFunctor #-}
module Data.Crosswalk (
-- * Crosswalk
Crosswalk (..),
-- * Bicrosswalk
Bicrosswalk (..),
) where

import Control.Applicative (pure, (<$>))
import Control.Applicative (pure, (<$>), Const(..))
import Data.Bifoldable (Bifoldable (..))
import Data.Bifunctor (Bifunctor (..))
import Data.Foldable (Foldable (..))
import Data.Functor.Compose (Compose (..))
import Data.Functor.Identity (Identity (..))
import Data.Functor.Sum (Sum (..))
import Data.Functor.These (These1 (..))
import Data.Proxy (Proxy (..))
import Data.Vector.Generic (Vector)
import Prelude (Either (..), Functor (fmap), Maybe (..), id, (.))

import qualified Data.List.NonEmpty as NE
import qualified Data.Sequence as Seq
import qualified Data.Vector as V
import qualified Data.Vector.Generic as VG
Expand Down Expand Up @@ -55,15 +60,15 @@ instance Crosswalk [] where
crosswalk f (x:xs) = alignWith cons (f x) (crosswalk f xs)
where cons = these pure id (:)

instance Crosswalk NE.NonEmpty where
crosswalk f (x NE.:| []) = (NE.:| []) <$> f x
crosswalk f (x1 NE.:| x2 : xs) = alignWith cons (f x1) (crosswalk f (x2 NE.:| xs))
phadej marked this conversation as resolved.
Show resolved Hide resolved
where cons = these (NE.:| []) id (NE.<|)

instance Crosswalk Seq.Seq where
crosswalk f = foldr (alignWith cons . f) nil where
cons = these Seq.singleton id (Seq.<|)

instance Crosswalk (These a) where
crosswalk _ (This _) = nil
crosswalk f (That x) = That <$> f x
crosswalk f (These a x) = These a <$> f x

crosswalkVector :: (Vector v a, Vector v b, Align f)
=> (a -> f b) -> v a -> f (v b)
crosswalkVector f = fmap VG.fromList . VG.foldr (alignWith cons . f) nil where
Expand All @@ -72,12 +77,37 @@ crosswalkVector f = fmap VG.fromList . VG.foldr (alignWith cons . f) nil where
instance Crosswalk V.Vector where
crosswalk = crosswalkVector

instance Crosswalk (Either e) where
crosswalk _ (Left _) = nil
crosswalk f (Right x) = Right <$> f x

instance Crosswalk (These a) where
crosswalk _ (This _) = nil
crosswalk f (That x) = That <$> f x
crosswalk f (These a x) = These a <$> f x

instance Crosswalk ((,) a) where
crosswalk fun (a, x) = fmap ((,) a) (fun x)

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

instance Crosswalk Proxy where
crosswalk _ _ = nil

instance Crosswalk (Const r) where
crosswalk _ _ = nil

instance (Crosswalk f, Crosswalk g) => Crosswalk (Sum f g) where
crosswalk f (InL xs) = InL <$> crosswalk f xs
crosswalk f (InR xs) = InR <$> crosswalk f xs

instance (Crosswalk f, Crosswalk g) => Crosswalk (These1 f g) where
crosswalk f (This1 xs) = This1 <$> crosswalk f xs
crosswalk f (That1 ys) = That1 <$> crosswalk f ys
crosswalk f (These1 xs ys) = alignWith go (crosswalk f xs) (crosswalk f ys)
where go = these This1 That1 These1

instance (Crosswalk f, Crosswalk g) => Crosswalk (Compose f g) where
crosswalk f
= fmap Compose -- can't coerce: maybe the Align-able thing has role nominal
Expand Down Expand Up @@ -113,3 +143,6 @@ instance Bicrosswalk These where
bicrosswalk f _ (This x) = This <$> f x
bicrosswalk _ g (That x) = That <$> g x
bicrosswalk f g (These x y) = align (f x) (g y)

instance Bicrosswalk Const where
bicrosswalk f _ (Const x) = Const <$> f x
17 changes: 14 additions & 3 deletions these-tests/test/Tests/Crosswalk.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@
{-# LANGUAGE ScopedTypeVariables #-}
module Tests.Crosswalk (crosswalkProps) where

import Control.Applicative (Const)
import Control.Monad.Trans.Instances ()
import Data.Functor.Compose (Compose (..))
import Data.Functor.Identity (Identity (..))
import Data.Functor.Sum (Sum)
import Data.Functor.These (These1)
import Data.List.NonEmpty (NonEmpty)
import Data.Map (Map)
import Data.Proxy (Proxy)
import Data.Semigroup (Semigroup (..))
import Data.Sequence (Seq)
import Data.Typeable (Typeable, typeOf1)
Expand All @@ -27,13 +32,19 @@ import Tests.Orphans ()

crosswalkProps :: TestTree
crosswalkProps = testGroup "Crosswalk"
[ crosswalkLaws (P :: P [])
[ crosswalkLaws (P :: P Identity)
, crosswalkLaws (P :: P Maybe)
, crosswalkLaws (P :: P Identity)
, crosswalkLaws (P :: P (These Int))
, crosswalkLaws (P :: P [])
, crosswalkLaws (P :: P NonEmpty)
, crosswalkLaws (P :: P Seq)
, crosswalkLaws (P :: P V.Vector)
, crosswalkLaws (P :: P (Either Int))
, crosswalkLaws (P :: P (These Int))
, crosswalkLaws (P :: P ((,) Int))
, crosswalkLaws (P :: P Proxy)
, crosswalkLaws (P :: P (Const Int))
, crosswalkLaws (P :: P (Sum [] []))
, crosswalkLaws (P :: P (These1 [] []))
, crosswalkLaws (P :: P (Compose [] []))
]

Expand Down