我理解没有“位置”参数的意思是,所有函数仅取一个变量并返回一个函数以对其余参数进行运算,但这就是我想做的:
从一些我用来格式化带有前置项,分隔符和结束项的列表的功能开始。
Prelude> formatList start end sep xs = start ++ (intercalate . separator ( map show xs )) ++ end
像这样工作:
Prelude Data.List> formatList "(" ")" "," [1..10]
"(1,2,3,4,5,6,7,8,9,10)"
很酷,相同的想法可以用于xml标签:
Prelude Data.List> formatList "<meow>" "</meow>" "" [1..10]
"<meow>12345678910</meow>"
本着重用功能和简洁性的精神,让我们做到这一点,这样我们就不必通过使函数仅从单词“ tag”产生打开和关闭来键入喵喵标签的冗余部分。 / p>
Prelude Data.List> tagger tag item = "<" ++ tag ++ ">" ++ item ++ "</" ++ tag ++ ">"
Prelude Data.List> tagger "div" "contents"
"<div>contents</div>"
因此,现在让一些标记制作器返回开始和结束,我可以为formatList函数添加第二个参数:
Prelude Data.List> tagMaker tag = ("<" ++ tag ++ ">", "</" ++ tag ++ ">")
看起来不错:
Prelude Data.List> tagMaker "div"
("<div>","</div>")
现在尝试一下。实际行为:
Prelude Data.List> formatList (tagMaker "div") "" [1..10]
<interactive>:49:13: error:
• Couldn't match expected type ‘[Char]’
with actual type ‘([Char], [Char])’
• In the first argument of ‘formatList’, namely ‘(tagMaker "div")’
In the expression: formatList (tagMaker "div") "" [1 .. 10]
In an equation for ‘it’:
it = formatList (tagMaker "div") "" [1 .. 10]
所需行为:
formatList (tagMaker "div") "" [1..10]
"<div>12345678910</div>
使tagMaker函数能够为希望采用第一个值,然后是第二个值的函数所用的正确方法是什么?如果这完全不是习惯用法,那么正确的成语是什么?
答案 0 :(得分:9)
命名参数的usual trick似乎很有趣。
data Formatter = Formatter { start, end, sep :: String }
formatList :: Show a => [a] -> Formatter -> String
formatList xs fmt = start fmt ++ intercalate (sep fmt) (map show xs) ++ end fmt
with :: Formatter
with = Formatter "" "" ""
现在您的原始通话如下:
formatList [1..10] with { start = "(", end = ")", sep = "," }
formatList [1..10] with { start = "<meow>", end = "</meow>" }
您可以通过以下方式创建格式化工厂:
xmlTag :: String -> Formatter
xmlTag t = with { start = "<" ++ t ++ ">", end = "</" ++ t ++ ">" }
用法如下:
formatList [1..10] (xmlTag "div") -- use the default separator
formatList [1..10] (xmlTag "div") { sep = "," } -- specify a separator
答案 1 :(得分:1)
只是简单易用的formatList
,因此它以2元组作为第一个参数,而不是两个单独的参数。
> :t formatList
formatList :: Show a => String -> String -> String -> [a] -> String
> :t uncurry formatList
uncurry formatList :: Show a => (String, String) -> String -> [a] -> String
> (uncurry formatList) (tagMaker "div") "" [1..10]
"<div>12345678910</div>
但是,我只是更加明确地使用了tagMaker
的返回值。上面的方法仅适用于tagMaker
准确地向formatList
提供前两个参数。
> let (b,e) = tagMaker "div" in formatList b e "" [1..10]
"<div>12345678910</div>"