[Haskell-cafe] Polyvariadic functions operating with a monoid

Kevin Jardine kevinjardine at gmail.com
Sun Oct 3 03:24:00 EDT 2010


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]

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)



More information about the Haskell-Cafe mailing list