首页 > 解决方案 > 将值渲染到 Haskell 中的项目和中间项目中

问题描述

在进行用户界面编程时,我经常遇到需要渲染一个值列表并在渲染的值之间添加一些相关信息。在下面的代码示例中,我将数值呈现为出现在括号中的字符串,并将两个值的距离呈现为放置在值呈现之间的字符串。该代码有效,但我想知道该mystery函数的实现是否可作为 Haskell 标准库的一部分。我也对其他库中用于此函数的名称感兴趣,因为使用人类可读的单词可以更轻松地进行谷歌搜索。

mystery :: (a -> b) -> (a -> a -> b) -> [a] -> [b]
mystery n d [] = []
mystery n d [x] = [n x]
mystery n d (x:xs) = (n x) : (d x (head xs)) : mystery n d xs

node x = "(" ++ show x ++ ")"
distance x y = "-" ++ (show $ abs $ x - y) ++ "-"
render xs = concat $ mystery node distance xs
-- render [25, 68, 54, 15] == "(25)-43-(68)-14-(54)-39-(15)"

标签: haskell

解决方案


你的mystery函数实际上是同时做几件事,如果你把这些行为分开,可能会更容易看到发生了什么。

首先,您正在映射n所有元素。我们可以把它写成fmap n xs。接下来,您正在d x y为所有成对的相邻元素xy. 我们可以把它写成zipWith d xs (tail xs)

最后一步是采用这两种结构并制作一个新列表,其中包含在它们之间来回交替的元素。有趣的是,这是一个9 年前提出的问题,但仍然没有一个超级令人满意的答案。可能最简单的答案是定义自己的函数:

alternate [] ys = ys
alternate (x:xs) ys = x : alternate ys xs

然后,我们可以定义mystery为单线:

mystery n d x = alternate (fmap n x) (zipWith d x (tail x))

如果您真的希望它成为单线,那么我能想到的最好的方法就是使用concat并且transpose以一种时髦的方式:

mystery n d x = concat $ transpose $ (pure $ fmap n x) <> (pure $ zipWith d x (tail x))

基本上,我们使用 将两个组件制作成单例列表pure,将它们与 融合在一起<>,然后transposeing 这个“列表列表”以正确散布元素,并concat生成结果。


推荐阅读