Search code examples
haskellblaze-html

Can't intersperse " " and unwords be used as drop in replacements for each other?


I was trying to rewrite:

return $ renderHtml $ mconcat $ intersperse " " $ catMaybes links

Which works just fine, into:

return $ renderHtml $ mconcat $ unwords $ catMaybes links

but it is returning:

Couldn't match type ‘Char’
               with ‘blaze-markup-0.7.0.2:Text.Blaze.Internal.MarkupM ()’
Expected type: H.Html
  Actual type: Char
In the second argument of ‘($)’, namely
  ‘mconcat $ unwords $ catMaybes links’
In the second argument of ‘($)’, namely
  ‘renderHtml $ mconcat $ unwords $ catMaybes links’
In a stmt of a 'do' block:
  return $ renderHtml $ mconcat $ unwords $ catMaybes links

I'm not the greatest with Haskell yet, but I thought intersperse " " and unwords where just drop in replacements for one another?

Edit: Ultimately, I'd like to figure out a way to use unwords... Figuring out why it's giving me the error and how I can work around it is the goal! =)


Solution

  • The unwords :: [String] -> String function only works on lists of Strings. What you have is a list of values of type MarkupM ().

    The reason why intersperse :: a -> [a] -> [a] works is that it works of list on any type. With OverloadedStrings pragma the " " value has type MarkupM (because that type has an instance for IsString). The intersperse function takes a list of these markup values and puts spaces in between them but still returns a list of markup values. Finally mconcat joins the list into a single value still of type MarkupM (). With some pseudo data constructor you can imagine the values like this:

    [Markup "foo", Markup "bar", Markup "baz"] -- returned by catMaybes links
    [Markup "foo", Markup " ", Markup "bar", Markup " ", Markup "baz"] -- after intersperse
    Markup "foo bar baz" -- after mconcat
    

    There is no easy way to get unwords to work in this case as you don't have strings and converting to strings would lose you some benefits. Having the markup encapsulated in appropriate wrapper makes sure that you do not produce not well-formed HTML, for example.