Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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! =)

like image 950
Berkson Avatar asked Dec 20 '22 02:12

Berkson


2 Answers

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.

like image 114
Lubomír Sedlář Avatar answered Jan 30 '23 12:01

Lubomír Sedlář


What you have will work if you use LANGUAGE OverloadedStrings.

Otherwise, use intersperse (text " ") instead of intersperse " ".

E.g.:

{-# LANGUAGE OverloadedStrings #-}

import Text.Blaze.Html
import Text.Blaze.Renderer.String
import Data.Maybe
import Data.List
import Data.Monoid

foo links = renderHtml $ mconcat $ intersperse " " $ catMaybes links
like image 39
ErikR Avatar answered Jan 30 '23 12:01

ErikR