[Haskell-cafe] Re: Polyvariadic functions operating with a monoid

Kevin Jardine kevinjardine at gmail.com
Sun Oct 3 16:04:21 EDT 2010


Luke, I had no idea polyvariadic functions would be controversial.

Yes, in my original case the function would be trivial:

toMonoid k =  [toString k]

I do prefer the less cluttered look. I think that

(poly value1 value2 value3)

is easier to follow when the values are all of related types (in my
case, all in the same type class).

But in the more general Monoid case there would not necessarily be a
list result.

Eg.

sumOf 1 2 3

could also be implemented using a Monoid approach with mempty = 0 and
mappend = +

Kevin

On Oct 3, 9:30 pm, Luke Palmer <lrpal... at gmail.com> wrote:
> On Sun, Oct 3, 2010 at 1:26 PM, Luke Palmer <lrpal... at gmail.com> wrote:
> > On Sun, Oct 3, 2010 at 1:24 AM, Kevin Jardine <kevinjard... at gmail.com> wrote:
> >> I had a situation where I had some related types that all had toString
> >> functions.
>
> >> Of course in Haskell, lists all have to be composed of values of
> >> exactly the same type, so instead of passing around lists of values
> >> with these related types, I created a polyvariadic function
> >> polyToString so that I could write:
>
> >> (polyToString value1 value2 value3 ... valueN)
>
> >> which would then become a list of strings:
>
> >> [toString value1, toString value2, ... , toString valueN]
>
> > First of all, you are not using the monoidal structure of String at
> > all.  This trick ought to work for any type whatsoever -- you're just
> > throwing them in a list.
>
> Oops, sorry for not reading your message more closely.  You were
> indeed talking about the monoidal structure of list.  So... nevermind
> about this comment.  :-P
>
>
>
> > Other than a few brackets, commas, and a repeated identifier (which
> > you can let-bind to shorten), what benefit is it giving you?  I
> > strongly recommend against polyvariadic functions.  While you get a
> > little bit of notational convenience, you lose composability.  There
> > are pains when you try to write a function that takes a polyvariadic
> > function as an argument, or when you try to feed the function values
> > from a list, etc.  The mechanisms to create polyvariadic functions are
> > brittle and hacky (eg. you cannot have a polymorphic return type, as
> > you want in this case).
>
> > Since all your values are known statically, I would recommend biting
> > the bullet and doing it the way you were doing it.
>
> >    [ s value1, s value2, s value3, ... ]
> >       where
> >       s x = toString x
>
> > (I had to eta expand s so that I didn't hit the monomorphism restriction)
>
> > When you want to be passing around "heterogeneous lists", it usually
> > works to convert them before you put them in the list, like you were
> > doing.
>
> >> I finally figured out how to do this, but it was a bit harder to
> >> figure this out than I expected, and I was wondering if it might be
> >> possible to create a small utility library to help other developers do
> >> this.
>
> >> It seems to me that in the general case, we would be dealing with a
> >> Monoid rather than a list of strings. We could have a toMonoid
> >> function and then return
>
> >> polyToMonoid value1 value2 ... valueN =
>
> >> (toMonoid value1) `mappend` (toMonoid value2) 'mappend' ... (toMonoid
> >> valueN)
>
> >> So anyone who wanted to convert a bunch of values of different types
> >> to a Monoid  could easily pass them around using polyToMonoid so long
> >> as they defined the appropriate toMonoid function.
>
> >> Basically, a generalised list.
>
> >> So I tried writing the following code but GHC said it had undecidable
> >> instances.
>
> >> Has this ever been done successfully?
>
> >> class Monoidable a where
> >>    toMonoid :: Monoid r => a -> r
>
> >> polyToMonoid :: (Monoidable a, Monoid r) => a -> r
> >> polyToMonoid k = polyToMonoid' k mempty
>
> >> class PolyVariadic p where
> >>    polyToMonoid' :: (Monoidable a, Monoid r) => a -> r -> p
>
> >> instance Monoid r => PolyVariadic r where
> >>    polyToMonoid' k ss = (toMonoid k) `mappend` ss
>
> >> instance (Monoidable a, Monoid r) => PolyVariadic (a -> r) where
> >>    polyToMonoid' k ss = (\a -> polyToMonoid' k (toMonoid a) `mappend`
> >> ss)
>
> >> _______________________________________________
> >> Haskell-Cafe mailing list
> >> Haskell-C... at haskell.org
> >>http://www.haskell.org/mailman/listinfo/haskell-cafe
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-C... at haskell.orghttp://www.haskell.org/mailman/listinfo/haskell-cafe


More information about the Haskell-Cafe mailing list