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)