On Sun, Oct 3, 2010 at 1:24 AM, Kevin Jardine <kevinjard...@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. 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-Cafe@haskell.org > http://www.haskell.org/mailman/listinfo/haskell-cafe > _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe