Fw: [Haskell-cafe] The difficulty of designing a sequence class

Brian Hulley brianh at metamilk.com
Mon Jul 31 20:17:54 EDT 2006

David Menendez wrote:
> Brian Hulley writes:
>> 1) Did Edison choose MonadPlus just because this fitted in with the
>> lack of multi-parameter typeclasses in H98?
> Instances of Monoid (and your ISeq) have kind *. Instances of
> MonadPlus (and Edison's Sequence) have kind * -> *.
> Functions like map, zip, and their variants are best defined in terms
> of type constructors.
> With Sequence, you have
>     zipWith :: (Sequence s) => (a -> b -> c) -> s a -> s b -> s c
> With ISeq, you'd have to do something like
>     zipWith :: (ISeq s1 a, ISeq s2 b, ISeq s3 c) =>
>         (a -> b -> c) -> s1 -> s2 -> s3
> which isn't able to make any assumptions about s1, s2, and s3 having
> the same structure.

 On the other hand it's more powerful because they can now have different 
structures ie was there any reason not to have:

 zipWith ::
      (Sequence s1, Sequence s2, Sequence s3) =>
      (a -> b -> c) -> s1 a -> s2 b -> s3 c

>> 3) Is it worth bothering to derive ISeq from Monoid (with the
>> possible extra inefficiency of the indirection through the
>> definitions for append = mappend etc or does the compiler completely
>> optimize this out)?
> I would expect the compiler to inline append.

Thanks - that's good news. I' probably still too much in C++ mode.

>> 4) Would it be worth reconsidering the rules for top level names so
>> that class methods could always be local to their class (ditto for
>> value constructors and field names being local to their type
>> constructor).
> Qualified module imports are the way to go, here. Do you really want
> to start writing "if x Eq/== y Num/+ 1 then ... "?

 I'm beginning to see that qualified module imports are indeed the only way 
to go, because the methods in a type class are only the "virtual" methods - 
often there are many other "methods" which are put outside the class to save 
space in the dictionary but which conceptually belong to the class thus 
putting the class + these extra functions in a single module wraps 
everything up into a conceptual unit.

      module Foldable
                      ( Foldable(..)
                      , reduceR
                      ) where

      class Foldable c a | c -> a where
         foldR :: (a -> b -> b) -> b -> [a] -> b
         -- ...

      reduceR :: Foldable c a => (a -> b -> b) -> (c -> b -> b)
      reduceR f xs y = foldR f y xs

 forms the single conceptual unit to use Foldable.foldR,  Foldable.reduceR 
etc so I'll have to retract my suggestion as regards classes... (Although 
I'm still concerned about value constructors and field names being in the 
top level instead of local to their type but changing this would require 
some changes to type inference (so that the constructors and field names 
could be used unqualified when the type at the given position is known eg by 
a top level type signature for the function or value) so that's more of a 
long term idea.)

 Regards, Brian.

Logic empowers us and Love gives us purpose.
Yet still phantoms restless for eras long past,
congealed in the present in unthought forms,
strive mightily unseen to destroy us.


More information about the Haskell-Cafe mailing list