[Haskell-cafe] Monomorphic containers, Functor/Foldable/Traversable WAS: mapM_ for bytestring

Michael Snoyman michael at snoyman.com
Fri Sep 13 07:51:23 CEST 2013

On Fri, Sep 13, 2013 at 5:38 AM, Mario Blažević <blamario at acanac.net> wrote:

> On 09/11/13 19:37, John Lato wrote:
>> I didn't see this message and replied privately to Michael earlier, so
>> I'm replicating my comments here.
>> 1.  Sooner or later I expect you'll want something like this:
>> class LooseMap c el el' where
>> lMap :: (el -> el') -> c el -> c el'
>> It covers the case of things like hashmaps/unboxed vectors that have
>> class constraints on elements.  Although maybe LooseFunctor or LFunctor
>> is a better name.
>> Probably something similar for Traversable would be good also, as would
>> a default instance in terms of Functor.
>> 2.  IMHO cMapM_ (and related) should be part of the Foldable class.
>> This is entirely for performance reasons, but there's no downside since
>> you can just provide a default instance.
>> 3.  I'm not entirely sure that the length* functions belong here.  I
>> understand why, and I think it's sensible reasoning, and I don't have a
>> good argument against it, but I just don't like it.  With those, and
>> mapM_-like functions, it seems that the foldable class is halfway to
>> being another monolithic ListLike.  But I don't have any better ideas
>> either.
>         If monolithic classes bother you, my monoid-subclasses package
> manages to break down the functionality into several classes. One big
> difference is that everything is based off Monoid rather than Foldable, and
> that has some big effects on the interface.
I'd point out what I'd consider a bigger difference: the type signatures
have changed in a significant way. With MonoFoldable, folding on a
ByteString would be:

    (Word8 -> b -> b) -> b -> ByteString -> b

With monoid-subclasses, you get:

    (ByteString -> b -> b) -> b -> ByteString -> b

There's certainly a performance issue to discuss, but I'm more worried
about semantics. Word8 tells me something very specific: I have one, and
precisely one, octet. ByteString tells me I have anywhere from 0 to 2^32 or
2^64  octets. Yes, we know from context that it will always be of size one,
but the type system can't enforce that invariant.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20130913/d8232b70/attachment.htm>

More information about the Haskell-Cafe mailing list