[Haskell-cafe] A quick question about distribution of finite maps.

Olaf Klinke olf at aatal-apotheke.de
Sun Jan 10 14:25:55 UTC 2021


On Sun, 2021-01-10 at 07:54 +0000, jack at jackkelly.name wrote:
> You may be thinking of https://hackage.haskell.org/package/smash and
> related packages.
> 
> -- Jack

Excellent, thanks for the hint! I shall also keep an eye on Emily's
packages in addition to Edward Kmett's when looking for category-
related stuff. The documentation mentions that Can is the categorical
product in Hask*. Unfortunately it does not say what the morphisms in
Hask* are. The linked ncatlab page suggests the morphisms are point-
preserving functions, which would fit Kleisli Maybe. 
The documentation of Data.Can also does not state whether canCurry and
canUncurry are mutually inverse. If so, that still does not contradict
MigMit because the first argument to canCurry might not preserve the
point, i.e. might not be a morphism of Hask*. Likewise, if the first
argument k to canUncurry has k Nothing Nothing = Just _ then canUncurry
k does not preserve the point, i.e. is not an element of Hask*. 

Anyways, we have 

Maybe (OneOrBoth x y) ~ Maybe (These x y) ~ Can x y

with iso1 = can 
  (\x -> (Just x,Nothing))
  (\y -> (Nothing,Just y))
  (\x y -> (Just x,Just y))

but still no mention of an inverse. Or am I missing something? How to
constuct iso2 and pairKleisli using the combinators in Data.Can? 

Olaf

> 
> January 10, 2021 5:19 PM, "David Feuer" <david.feuer at gmail.com>
> wrote:
> 
> > I just don't want to take credit for anyone else's work. 
Neither do I, hence I mentioned you in my code. 

> > I have a very vague recollection that
> > Emily Pillmore may have looked at some related categorical stuff,
> > but I could easily be mistaken.
> > 
> > On Sun, Jan 10, 2021, 2:16 AM Olaf Klinke <olf at aatal-apotheke.de>
> > wrote:
> > 
> > > On Sat, 2021-01-09 at 18:04 -0500, David Feuer wrote:
> > > > `These` is not my own invention. It's in the `these` package.
> > > 
> > > Then please interpret my "due to David Feuer" as "brought into
> > > this
> > > discussion by David Feuer". I wonder whether These has ever been
> > > linked
> > > to categorical products in Kleisli Maybe before. There are
> > > Data.These.Combinators.justHere and justThere which are the same
> > > as my
> > > fstMaybe and sndMaybe. But combinators resulting in pairKleisli
> > > and
> > > iso1 seem to be missing from the these package.
> > > 
> > > Olaf
> > > 
> > > > On Sat, Jan 9, 2021, 5:41 PM Olaf Klinke <olf at aatal-apotheke.de
> > > > >
> > > > wrote:
> > > > 
> > > > > On Sat, 2021-01-09 at 22:26 +0100, MigMit wrote:
> > > > > > Actually, it's pretty easy to construct a type `P x y`, so
> > > > > > that
> > > > > > Maybe
> > > > > > (P x y) ~ (Maybe x, Maybe y). It would be
> > > > > > 
> > > > > > data OneOrBoth x y = Left' x | Right' y | Both x y
> > > > > > 
> > > > > > The isomorphism is, I think, obvious
> > > > > > 
> > > > > > iso1 :: Maybe (OneOrBoth x y) -> (Maybe x, Maybe y)
> > > > > > iso1 Nothing = (Nothing, Nothing)
> > > > > > iso1 (Just (Left' x)) = (Just x, Nothing)
> > > > > > iso1 (Just (Right' y)) = (Nothing, Just y)
> > > > > > iso1 (Just (Both x y)) = (Just x, Just y)
> > > > > > 
> > > > > > iso2 :: (Maybe x, Maybe y) -> Maybe (OneOrBoth x y)
> > > > > > iso2 = -- left as an excersize for the reader
> > > > > > 
> > > > > > And indeed, "OneOrBoth" would be a cartesian product
> > > > > > functor in
> > > > > > the
> > > > > > category of finite types (and maps).
> > > > > 
> > > > > I stand corrected. Below is the full code, in case anyone
> > > > > wants to
> > > > > play
> > > > > with it.
> > > > > 
> > > > > import Control.Arrow ((&&&))
> > > > > 
> > > > > -- due to David Feuer
> > > > > data OneOrBoth x y = Left' x | Right' y | Both x y
> > > > > 
> > > > > iso2 :: (Maybe x,Maybe y) -> Maybe (OneOrBoth x y)
> > > > > iso2 p = case p of
> > > > > (Nothing,Nothing) -> Nothing
> > > > > (Just x,Nothing) -> (Just (Left' x))
> > > > > (Nothing,Just y) -> (Just (Right' y))
> > > > > (Just x, Just y) -> (Just (Both x y))
> > > > > 
> > > > > -- (OneOrBoth x) is a functor on Kleisli Maybe
> > > > > fmapKleisli :: (a -> Maybe b) ->
> > > > > OneOrBoth x a -> Maybe (OneOrBoth x b)
> > > > > fmapKleisli k (Left' x) = Just (Left' x)
> > > > > fmapKleisli k (Right' a) = fmap Right' (k a)
> > > > > fmapKleisli k (Both x a) = fmap (Both x) (k a)
> > > > > 
> > > > > -- is OneOrBoth the cartesian product? Seems so:
> > > > > 
> > > > > pairKleisli :: (a -> Maybe x) ->
> > > > > (a -> Maybe y) ->
> > > > > a -> Maybe (OneOrBoth x y)
> > > > > pairKleisli f g = iso2 . (f &&& g)
> > > > > 
> > > > > fstMaybe :: OneOrBoth x y -> Maybe x
> > > > > fstMaybe (Left' x) = Just x
> > > > > fstMaybe (Both x _) = Just x
> > > > > fstMaybe (Right' _) = Nothing
> > > > > 
> > > > > sndMaybe :: OneOrBoth x y -> Maybe y
> > > > > sndMaybe (Left' _) = Nothing
> > > > > sndMaybe (Right' y) = Just y
> > > > > sndMaybe (Both _ y) = Just y
> > > > > 
> > > > > > But it won't be cartesian closed. If it were, then for any
> > > > > > finite
> > > > > > X
> > > > > > and Y we should have
> > > > > > 
> > > > > > Maybe (X^Y) ~
> > > > > > () -> Maybe (X^Y) ~
> > > > > > OneOrBoth () Y -> Maybe X ~
> > > > > > (() -> Maybe X, Y -> Maybe X, ((), Y) -> Maybe X) ~
> > > > > > (Maybe X, Y -> Maybe X, Y -> Maybe X)
> > > > > > 
> > > > > > so
> > > > > > 
> > > > > > X^Y ~ (X, Y -> Maybe X, Y -> Maybe X)
> > > > > > 
> > > > > > But then
> > > > > > 
> > > > > > Z -> Maybe (X^Y) ~
> > > > > > Z -> (Maybe X, Y -> Maybe X, Y -> Maybe X) ~
> > > > > > (Z -> Maybe X, (Z, Y) -> Maybe X, (Z, Y) -> Maybe X) ~
> > > > > > 
> > > > > > and
> > > > > > 
> > > > > > OneOrBoth Z Y -> Maybe X ~
> > > > > > (Z -> Maybe X, Y -> Maybe X, (Z, Y) -> Maybe X)
> > > > > > 
> > > > > > We see that those aren't the same, they have a different
> > > > > > number
> > > > > > of
> > > > > > elements, so, no luck.
> > > > > 
> > > > > Doesn't this chain of isomorphisms require () to be the
> > > > > terminal
> > > > > object, or did you take () as synonym for the terminal object
> > > > > in
> > > > > the
> > > > > category? For example, there are several functions of the
> > > > > type
> > > > > Bool -> Maybe ().
> > > > > So the terminal object in Kleisli Maybe would be Void,
> > > > > because
> > > > > Maybe
> > > > > Void ~ (). We'd need to make fields in OneOrBoth strict to
> > > > > have an
> > > > > isomorphism OneOrBoth Void a ~ a, just as the true
> > > > > categorical
> > > > > product
> > > > > in (->) is the strict pair.
> > > > > 
> > > > > Olaf
> > > > > 
> > > > > > > On 9 Jan 2021, at 22:01, Olaf Klinke <
> > > > > > > olf at aatal-apotheke.de>
> > > > > > > wrote:
> > > > > > > 
> > > > > > > > Hello!
> > > > > > > > 
> > > > > > > > Finite maps from `"containers" Data.Map` look like they
> > > > > > > > may
> > > > > > > > form
> > > > > > > > a
> > > > > > > > Cartesian closed category. So it makes sense to ask if
> > > > > > > > the
> > > > > > > > rule
> > > > > > > > _α ⇸
> > > > > > > > (β ⇸ γ) ≡ ⟨α; β⟩ ⇸ γ ≡ ⟨β; α⟩ ⇸ γ ≡ β ⇸ (α ⇸ γ)_ that
> > > > > > > > holds
> > > > > > > > in
> > > > > > > > such
> > > > > > > > categories does hold for finite maps. Note that, a map
> > > > > > > > being
> > > > > > > > a
> > > > > > > > functor, this also may be seen as _f (g α) ≡ g (f α)_,
> > > > > > > > which
> > > > > > > > would
> > > > > > > > work if maps were `Distributive` [1].
> > > > > > > > 
> > > > > > > > It looks to me as though the following definition might
> > > > > > > > work:
> > > > > > > > 
> > > > > > > > distribute = unionsWith union . mapWithKey (fmap .
> > > > > > > > singleton)
> > > > > > > > 
> > > > > > > > — And it works on simple examples. _(I checked the law
> > > > > > > > `distribute ∘
> > > > > > > > distribute ≡ id` — it appears to be the only law
> > > > > > > > required.)_
> > > > > > > > 
> > > > > > > > Is this definition correct? Is it already known and
> > > > > > > > defined
> > > > > > > > elsewhere?
> > > > > > > > 
> > > > > > > > [1]:
> > > > > > > > 
> > > https://hackage.haskell.org/package/distributive-0.6.2.1/docs/Data-Distributive.html#t:Distributive
> > > > > > > Hi Ignat,
> > > > > > > 
> > > > > > > TL;DR: No and no.
> > > > > > > 
> > > > > > > The documentation says that every distributive functor is
> > > > > > > of
> > > > > > > the
> > > > > > > form
> > > > > > > (->) x for some x, and (Map a) is not like this.
> > > > > > > 
> > > > > > > If Maps were a category, what is the identity morphism?
> > > > > > > 
> > > > > > > Let's put the Ord constraint on the keys aside, Tom
> > > > > > > Smeding has
> > > > > > > already
> > > > > > > commented on that. Next, a Map is always finite, hence
> > > > > > > let's
> > > > > > > pretend
> > > > > > > that we are working inside the category of finite types
> > > > > > > and
> > > > > > > functions.
> > > > > > > Then the problems of missing identity and missing Ord go
> > > > > > > away.
> > > > > > > Once
> > > > > > > that all types are finite, we can assume an enumerator.
> > > > > > > That
> > > > > > > is,
> > > > > > > each
> > > > > > > type x has an operation
> > > > > > > enumerate :: [x]
> > > > > > > which we will use to construct the inverse of
> > > > > > > flip Map.lookup :: Map a b -> a -> Maybe b
> > > > > > > thereby showing that a Map is nothing but a memoized
> > > > > > > version of
> > > > > > > a
> > > > > > > Kleisli map (a -> Maybe b). Convince yourself that Map
> > > > > > > concatenation
> > > > > > > has the same semantics as Kleisli composition (<=<).
> > > > > > > Given a
> > > > > > > Kleisli
> > > > > > > map k between finite types, we build a Map as follows.
> > > > > > > \k -> Map.fromList (enumerate >>= (\a -> maybe []
> > > > > > > (pure.(,) a)
> > > > > > > (k
> > > > > > > a)))
> > > > > > > 
> > > > > > > With that knowledge, we can answer your question by
> > > > > > > deciding:
> > > > > > > Is
> > > > > > > the
> > > > > > > Kleisli category of the Maybe monad on finite types
> > > > > > > Cartesian
> > > > > > > closed?
> > > > > > > Short answer: It is not even Cartesian.
> > > > > > > There is an adjunction between the categories (->) and
> > > > > > > (Kleisli
> > > > > > > m)
> > > > > > > for
> > > > > > > every monad m, where
> > > > > > > * The left adjoint functor takes
> > > > > > > types x to x,
> > > > > > > functions f to return.f
> > > > > > > * The right adjoint functor takes
> > > > > > > types x to m x,
> > > > > > > Kleisli maps f to (=<<) f
> > > > > > > Right adjoint functors preserve all existing limits,
> > > > > > > which
> > > > > > > includes
> > > > > > > products. Therefore, if (Kleisli m) has binary products,
> > > > > > > then m
> > > > > > > must
> > > > > > > preserve them. So if P x y was the product of x and y in
> > > > > > > Kleisli m,
> > > > > > > then m (P x y) would be isomorphic to (m x,m y). This
> > > > > > > seems not
> > > > > > > to
> > > > > > > hold
> > > > > > > for m = Maybe: I can not imagine a type constructor P
> > > > > > > where
> > > > > > > Maybe (P x y) ~ (Maybe x,Maybe y).
> > > > > > > In particular, P can not be (,). The only sensible
> > > > > > > Kleisli
> > > > > > > projections
> > > > > > > from (x,y) would be fst' = return.fst and snd' =
> > > > > > > return.snd.
> > > > > > > Now
> > > > > > > think
> > > > > > > of two Kleisli maps f :: Bool -> Maybe x, g :: Bool ->
> > > > > > > Maybe y.
> > > > > > > Assume
> > > > > > > that f True = Just x for some x and g True = Nothing. In
> > > > > > > order
> > > > > > > to
> > > > > > > satisfy g True = (snd' <=< (f&&&g))True, the unique pair
> > > > > > > arrow
> > > > > > > (f&&&g)
> > > > > > > would need to map True to Nothing, but then f True =
> > > > > > > (fst' <=<
> > > > > > > (f&&&g))
> > > > > > > True can not hold. We conclude that (Kleisli Maybe) does
> > > > > > > not
> > > > > > > even
> > > > > > > have
> > > > > > > categorical products, so asking for Cartesian closure
> > > > > > > does not
> > > > > > > make
> > > > > > > sense.
> > > > > > > 
> > > > > > > You might ask for a weaker property: For every type x,
> > > > > > > ((,) x)
> > > > > > > is a
> > > > > > > functor on (Kleisli Maybe). Indeed, the following works
> > > > > > > because
> > > > > > > ((,) x)
> > > > > > > is a polynomial functor.
> > > > > > > fmapKleisli :: Functor m => (a -> m b) -> (x,a) -> m
> > > > > > > (x,b)
> > > > > > > fmapKleisli f (x,a) = fmap ((,) x) (f a)
> > > > > > > Thus you may ask whether this functor has a right adjoint
> > > > > > > in
> > > > > > > the
> > > > > > > Kleisli category of Maybe. This would be a type
> > > > > > > constructor g
> > > > > > > with
> > > > > > > a
> > > > > > > natural isomorphism
> > > > > > > 
> > > > > > > (x,a) -> Maybe b ~ a -> Maybe (g b).
> > > > > > > 
> > > > > > > The first thing that comes to mind is to try
> > > > > > > g b = x -> Maybe b and indeed djinn can provide two
> > > > > > > functions
> > > > > > > going
> > > > > > > back and forth that have the right type, but they do not
> > > > > > > establish
> > > > > > > an
> > > > > > > isomorphism. I doubt there is such a right adjoint g, but
> > > > > > > can
> > > > > > > not
> > > > > > > prove
> > > > > > > it at the moment. The idea is that a function (x,a) ->
> > > > > > > Maybe b
> > > > > > > may
> > > > > > > decide for Nothing depending on both x and a, and
> > > > > > > therefore the
> > > > > > > image
> > > > > > > function under the isomorphism must map every a to Just
> > > > > > > (g b)
> > > > > > > and
> > > > > > > delay
> > > > > > > the Nothing-decision to the g b. But for the reverse
> > > > > > > isomorphism
> > > > > > > you
> > > > > > > can have functions that do not always return Just (g b)
> > > > > > > and
> > > > > > > there
> > > > > > > is no
> > > > > > > preimage for these.
> > > > > > > 
> > > > > > > Regards,
> > > > > > > Olaf
> > > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > _______________________________________________
> > > > > > > Haskell-Cafe mailing list
> > > > > > > To (un)subscribe, modify options or view archives go to:
> > > > > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> > > > > > > Only members subscribed via the mailman list are allowed
> > > > > > > to
> > > > > > > post.



More information about the Haskell-Cafe mailing list