I want to build a list of different things which have one property in common, namely, they could be turned into string. The object-oriented approach is straightforward: defi
I would do something like this:
newtype Strings = Strings { getStrings :: [String] }
newtype DiffList a = DiffList { getDiffList :: [a] -> [a] }
instance Monoid (DiffList a) where
mempty = DiffList id
DiffList f `mappend` DiffList g = DiffList (f . g)
class ShowList a where
showList' :: DiffList String -> a
instance ShowList Strings where
showList' (DiffList xs) = Strings (xs [])
instance (Show a, ShowList b) => ShowList (a -> b) where
showList' xs x = showList' $ xs `mappend` DiffList (show x :)
showList = showList' mempty
Now, you can create a ShowList
as follows:
myShowList = showList 1 "blah" 3.14
You can get back a list of strings using getStrings
as follows:
myStrings = getStrings myShowList
Here's what's happening:
A value of the type ShowList a => a
could be:
Strings
newtype wrapper.Show
to an instance of ShowList
.This means that the function showList
is a variadic argument function which takes an arbitrary number of printable values and eventually returns a list of strings wrapped in a Strings
newtype wrapper.
You can eventually call getStrings
on a value of the type ShowList a => a
to get the final result. In addition, you don't need to do any explicit type coercion yourself.
Advantages:
show
in front of every element.For more information on functions with variadic arguments, read the answer to the following question:
How does Haskell printf work?