On Sun, Oct 3, 2010 at 1:26 PM, Luke Palmer <lrpal...@gmail.com> wrote: > 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.
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-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