【发布时间】:2014-11-05 02:16:53
【问题描述】:
我有一个列表,例如 [1, 2, 3, 4, 5],我必须复制列表中的每个元素以形成像 [1, 1, 2, 2, 3, 4, 4 这样的列表, 5, 5]。
作为提示,我们提到了 concat 函数,它将列表列表扁平化为单个列表。但是为了尝试了解如何更好地在 Haskell 中进行此操作,我正在尝试手动进行。这是我的尝试:
duplicate :: [a] -> [a]
duplicate [] = []
duplicate (x:xs) = x : (x:xs) duplicate xs
带有错误信息:
Couldn't match expected type `((a0 -> Bool) -> [a0] -> [a0])
-> [a] -> [a]'
with actual type `[a]'
The function `x : xs' is applied to two arguments,
but its type `[a]' has none
In the second argument of `(:)', namely `(x : xs) myTakeWhile xs'
In the expression: x : (x : xs) myTakeWhile xs
Failed, modules loaded: none.
我的想法是,你将列表的头部cons到整个列表,然后递归调用这个列表尾部的函数。以伪代码为例:
duplicate [1, 2, 3]
1 : [1, 2, 3] duplicate [2, 3]
2 : [2, 3] duplicate [3]
3: [3] duplicate []
return list [1, 1, 2, 2, 3, 3]
这是解决此问题的惯用方式吗?我在语法上的尝试中哪里出错了?我不是在寻找替代的、更有效的代码解决方案,我只是想习惯于用函数式的方式解决问题,而不是用命令式的方式看待事物。
谢谢!
【问题讨论】:
-
x y始终表示“将函数x应用于参数y”。在[1, 2, 3] function中,[1, 2, 3]不是函数,因此会出现类型错误。 -
你的想法是对的,但是你错误地应用了函数。代码尝试将列表视为您将
myTakeWhile和列表传递给的函数。也许,先复制尾部,然后将头部附加两次。 -
myTakeWhile 是一个复制错误,试图递归调用重复。已编辑。
标签: haskell