【问题标题】:Rendering values into items and intermediate items in Haskell将值渲染到 Haskell 中的项目和中间项目中
【发布时间】:2020-12-20 21:08:02
【问题描述】:

在进行用户界面编程时,我经常遇到需要渲染一个值列表并在渲染的值之间添加一些相关信息。在下面的代码示例中,我将数值呈现为出现在括号中的字符串,并将两个值的距离呈现为放置在值呈现之间的字符串。该代码有效,但我想知道 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)"

【问题讨论】:

  • 我找不到比您的方法更简单的方法了。原则上我们可以使用concat $ zipWith next ys (tail ys) where next x y = [n x, d x y],但这会错过最后一个数字。我们需要一个更通用的zipWith,它允许处理第一个列表非空但第二个列表非空的情况。我在图书馆找不到那个。我们可以使用++ [n $ last ys],但这在我看来很难看。

标签: haskell


【解决方案1】:

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

首先,您将n 映射到所有元素上。我们可以写成fmap n xs。接下来,您将为所有相邻元素对 xy 构造新元素 d x y。我们可以写成zipWith d xs (tail xs)

最后一步是采用这两个结构并创建一个新列表,其中包含在它们之间来回交替的元素。有趣的是,这是一个question asked 9 years ago,但仍然没有一个非常令人满意的答案。可能最简单的答案是定义自己的函数:

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

如果您真的希望它是单行的,我能想到的最好办法就是以一种时髦的方式使用 concattranspose

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

基本上,我们使用pure 从两个组件中创建单例列表,将它们与&lt;&gt; 融合在一起,然后transposeing 这个“列表列表”以正确散布元素,然后@987654338 @结果。

【讨论】:

  • 感谢您的回答! alternate 函数似乎有时被称为 flatZipalternate 这个名字也不错。这听起来像是您在使用 Python 生成器时可能使用的名称。由于懒惰的性质,它可能与 Haskell 一起使用,但在不同的语言和环境中可能无法很好地工作。大多数标准库中似乎缺少alternate / flatZip 函数,这很奇怪。我添加了对详细说明 flatZip 方法的原始问题的答案。也许有一天它会出现在标准库中,谁知道呢。
猜你喜欢
  • 2018-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-26
  • 2017-02-22
  • 2020-09-17
  • 2019-02-01
相关资源
最近更新 更多