purescript-filterable icon indicating copy to clipboard operation
purescript-filterable copied to clipboard

Contravariant functor subclass

Open no-longer-on-githu-b opened this issue 9 years ago • 4 comments

It is useful to have:

class (Contravariant f) <= Contrafilterable f where
  cfilter :: forall a. (a -> Boolean) -> f a -> f a
  cfilterCmap :: forall a b. (b -> Maybe a) -> f a -> f b
  cpartition :: ...
  cpartitionCmap :: ...

An example use case is my logging library, which currently provides this method as a function: https://pursuit.purescript.org/packages/purescript-logging/0.0.3/docs/Control.Logger#v:cfilter

no-longer-on-githu-b avatar Aug 26 '16 07:08 no-longer-on-githu-b

Thanks, I've been thinking about this. Although I haven't tested it; I think we can define these in terms of Decidable. Something like:

cfilterCmap :: forall a b f. Decidable f => (a -> Maybe b) -> f b -> f a
cfilterCmap f = choose (maybe (Left unit) Right <<< f) conquer

I'm also thinking about a Profunctor version.

LiamGoodacre avatar Aug 27 '16 15:08 LiamGoodacre

Very interesting! It seems Logger is an instance of Decidable.

no-longer-on-githu-b avatar Aug 27 '16 16:08 no-longer-on-githu-b

I've been thinking about this for a while. If we look at the types:

choose :: (a -> b + c) -> f b * f c -> f a
altMap :: (b + c -> a) -> f b * f c -> f a
altMap f l r = map f (alt (map Left l) (map Right r))  

The difference here is that the function argument has been reversed.

Now if we compare partitionMap with choose:

choose       :: (a -> b + c) -> f b * f c -> f a
partitionMap :: (a -> b + c) -> f a -> f b * f c

The function argument is the same. If instead we reverse the function argument, as in the difference between altMap and choose, we get a kind of forking behaviour:

forkMap      :: (b + c -> a) -> f a -> f b * f c
partitionMap :: (a -> b + c) -> f a -> f b * f c

However, forkMap appears to be implementable just with cmap:

forkMap f = cmap (f <<< Left) &&& cmap (f <<< Right)

So now I'm a little confused :smile:.

LiamGoodacre avatar Aug 28 '16 10:08 LiamGoodacre

What if in addition to reversing the function argument, you swap out * for + in the result?

no-longer-on-githu-b avatar Oct 15 '16 23:10 no-longer-on-githu-b