我有一个列表,例如[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.
我的思维方式是你将列表的头部排在整个列表中,然后递归调用该列表尾部的函数。例如,在伪代码中:
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]
这是一种解决这个问题的惯用方法吗?我在语法上的尝试在哪里出错?我不是在寻找替代的,更有效的代码解决方案,我只是试图习惯于处理问题的功能性方式,而不是看待事物的必要方式。
谢谢!
答案 0 :(得分:3)
您正在寻找的定义是:
duplicate :: [a] -> [a]
duplicate [] = []
duplicate (x:xs) = x : x : duplicate xs
由于:
是一个右关联运算符,因此您可以将最后一个选项读作
duplicate (x:xs) = x : (x : (duplicate xs))
或
duplicate (x:xs) = (:) x ((:) x (duplicate xs))
请注意,[1, 2, 3]
只是1 : 2 : 3 : []
的缩写,当duplicate
应用于[1, 2, 3]
时,会使用第二种替代方法,因为它与模式{{1 (即x : xs
和x = 1
)。您希望结果以头部开始两次(这是定义的xs = 2 : 3 : []
部分),并继续使用重复的尾部(x : x : ...
部分)。