穿插" "和unwords不能互为替代吗?

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

我正在尝试重写:

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

工作正常,进入:

return $ renderHtml $ mconcat $ unwords $ catMaybes links

但它正在返回:

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

我还不是最棒的 Haskell,但我认为 intersperse " "unwords 哪里可以互换?

编辑:最终,我想找出一种使用unwords的方法...弄清楚为什么它会给我错误以及我如何能解决它是目标! =)

如果您使用 LANGUAGE OverloadedStrings,您所拥有的将会起作用。

否则,使用 intersperse (text " ") 而不是 intersperse " "

例如:

{-# 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

unwords :: [String] -> String 函数仅适用于 String 的列表。您拥有的是 MarkupM ().

类型的值列表

intersperse :: a -> [a] -> [a] 起作用的原因是它适用于任何类型的列表。使用 OverloadedStrings pragma," " 值具有类型 MarkupM(因为该类型具有 IsString 的实例)。 intersperse 函数获取这些标记值的列表并在它们之间放置空格,但仍然是 returns 标记值列表。最后 mconcat 将列表连接成一个仍然是 MarkupM () 类型的值。使用一些伪数据构造函数,您可以想象这样的值:

[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

没有简单的方法让 unwords 在这种情况下工作,因为您没有字符串并且转换为字符串会失去一些好处。例如,将标记封装在适当的包装器中可确保您不会生成格式不正确的 HTML。