[Haskell-cafe] Basic question concerning the category Hask (was:
concerning data constructors)
Jonathan Cast
jonathanccast at fastmail.fm
Sun Jan 6 00:38:19 EST 2008
On 5 Jan 2008, at 6:03 PM, Yitzchak Gale wrote:
> Jonathan Cast wrote:
>>>> The normal view taken by Haskellers is that the denotations of
>>>> Haskell types are CPPOs.
>>>> So:
>>>> (1) Must be monotone
>>>> (2) Must be continuous
>>>> (Needn't be strict, even though that messes up the resulting
>>>> category substantially).
>
> I wrote:
>>> I'm not convinced that the category is all that "messed up".
>
>> Well, no coproducts (Haskell uses a lifted version of the coproduct
>> from CPO).
>
> What goes wrong with finite coproducts? The obvious thing to
> do would be to take the disjoint union of the sets representing the
> types, identifying the copies of _|_.
This isn't a coproduct. If we have f x = 1 and g y = 2, then there
should exist a function h such that h . Left = f and h . Right = g,
i.e.,
h (Left x)
= f x
= 1
and
h (Right y)
= g y
= 2
But by your rule, Left undefined = Right undefined, so
1
= h (Left undefined)
= h (Right undefined)
= 2
Which is a contradiction. Identifying Left _|_ and Right _|_
produces a pointed CPO, but it's not a coproduct. Unless, of course,
your require your functions to be strict --- then both f and g above
become illegal, and repairing them removes the problem.
> What is the lifted version you are referring to?
Take the ordinary disjoint union, and then add a new _|_ element,
distinct from both existing copies of _|_ (which are still distinct
from each other).
>
>> Of course, Haskell makes things even worse by lifting the
>> product and exponential objects,
>
> OK, what goes wrong there, and what is the lifting?
Again, in Haskell, (_|_, _|_) /= _|_. The difference is in the function
f (x, y) = 1
which gives f undefined = undefined but f (undefined, undefined) =
1. Unfortunately, this means that (alpha, beta) has an extra _|_
element < (_|_, _|_), so it's not the categorical product (which
would lack such an element for the same reason as above).
This is partly an implementation issue --- compiling pattern matching
without introducing such a lifting requires a parallel implementation
--- and partly a semantic issue --- data introduces a single level of
lifting, every time it is used, and every constructor is completely
lazy.
Functions have the same issue --- in the presence of seq, undefined /
= const undefined.
Extensionality is a key part of the definition of all of these
constructions. The categorical rules are designed to require, in
concrete categories, that the range of the two injections into a
coproduct form a partition of the coproduct, the surjective pairing
law (fst x, snd x) = x holds, and the eta reduction law (\ x -> f x)
= f holds. Haskell flaunts all three; while some categories have few
enough morphisms to get away with this (at least some times), Hask is
not one of them.
jcc
More information about the Haskell-Cafe
mailing list