复制列表中的元素

时间:2014-10-29 13:22:56

标签: haskell

我有一个列表,例如[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]

这是一种解决这个问题的惯用方法吗?我在语法上的尝试在哪里出错?我不是在寻找替代的,更有效的代码解决方案,我只是试图习惯于处理问题的功能性方式,而不是看待事物的必要方式。

谢谢!

1 个答案:

答案 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 : xsx = 1)。您希望结果以头部开始两次(这是定义的xs = 2 : 3 : []部分),并继续使用重复的尾部(x : x : ...部分)。