-
Notifications
You must be signed in to change notification settings - Fork 49
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
Unalign
instances for sequence types? (list, vector, etc.)
#186
Comments
Fair observation. And obvious Maybe I have to think a bit about this. |
In my own work I realised that I reached for Here's how I've started thinking about it: class Functor f => Unzip f where
unzipWith :: (a -> (b, c)) -> f a -> (f b, f c)
unzipFmapDefault1 :: Unzip f => (a -> b) -> f a -> f b
unzipFmapDefault1 f = fst . unzipWith (\a -> (f a, ()))
unzipFmapDefault2 :: Unzip f => (a -> b) -> f a -> f b
unzipFmapDefault2 f = snd . unzipWith (\a -> ((), f a))
class Functor f => Partition f where
partitionWith :: (a -> Either b c) -> f a -> (f b, f c)
partitionFmapDefault1 :: Partition f => (a -> b) -> f a -> f b
partitionFmapDefault1 f = fst . partitionWith (Left . f)
partitionFmapDefault2 :: Partition f => (a -> b) -> f a -> f b
partitionFmapDefault2 f = snd . partitionWith (Right . f)
class (Unzip f, Partition f) => Unalign f where
unalignWith :: (a -> These b c) -> f a -> (f b, f c)
unalignUnzipWithDefault :: Unalign f => (a -> (b, c)) -> f a -> (f b, f c)
unalignUnzipWithDefault f = unalignWith (uncurry These . f)
unalignPartitionWithDefault :: Unalign f => (a -> Either b c) -> f a -> (f b, f c)
unalignPartitionWithDefault f = unalignWith (either This That . f) |
I will add here that catMaybesDefault :: Unalign f => f (Maybe a) -> f a
catMaybesDefault = snd . unalignWith (maybe (This ()) (These ())) So if we accept the proposed semantics and relax the inverse restriction, then all instances of Hence I argue that |
I'm creating this issue because I thought that
Unalign
was missing instances for sequences, like list and vector. I'm technically wrong, according to the class's laws, but I think it's still worth discussing.My intuition went like this: just as
Unzip
can be implemented for anyFunctor
, it looks likeUnalign
can be implemented for anyFilterable
:Despite my intuition, sequences don't satisfy one of the
Unalign
laws:uncurry align (unalign xs) ≡ xs
. They do satisfy the other, however:unalign (align xs ys) ≡ (xs, ys)
.While it's not a lawful
Unalign
implementation, I still feel likeunalignDefault
is a reasonable function, which is why I think this is worth talking about.unalign <-> uncurry align
is currently specified as an isomorphism, which rules out sequence types, but it seems reasonable to only requireunalign
to be a left inverse ofuncurry align
.Curiously,
Unzip
has a sort of "dual" version of this relaxation:unzip
is only required be the right inverse ofuncurry zip
, because requiring them to form an isomorphism would rule out map types.Proofs / working out
A quick proof for
Unalign []
to check that my intuition is lawful:uncurry align (unalign xs) ≡ xs
:It looks like it doesn't work out. A counterexample:
exists (xs :: [This a b]). uncurry align (unalign xs) != xs
:How does this law work out for
Map
, then?It works out because the
Map
"preserves keys"; each value has the same key before and afterunalign
ing.The other law does hold for lists:
unalign (align xs ys) ≡ (xs, ys)
. Less formally:unalign (align [] ys) ≡ ([], ys)
unalign (align xs []) ≡ (xs, [])
The text was updated successfully, but these errors were encountered: