我对该功能的实现有疑问:
wrap :: Int -> a -> [a] -> [a]
将x
插入列表n
中第xs
个位置。
wrap 1 '+' "a" : "+a+"
wrap 2 '+' "a" : "+a"
wrap 2 '+' "abcd" : "+ab+cd+"
wrap _ _ [] = []
wrap n x xs = insertAfter 0 xs
where insertAfter = undefined
一个人怎么能实现这个,我只是想不通。 编辑:
完整问题: 实现函数wrap,该函数生成一个列表,该列表以wrap的第二个参数(x)开头,然后是wrap的第三个参数(xs)的所有内容,如wrap的第一个参数(n)所指定的那样。重复直到第三个参数为空。在结果列表中,第n个元素应等于x。如果xs的长度可以被n整除,请在最后插入x。 提示:使用函数insertAfter来实现函数包装,该函数需要一个数字m和一个元素列表xs,当元素从xs中移除时,m会减少m,并在m达到0时插入x。
我几乎明白了:
wrap _ _ [] = []
wrap n x xs = insertAfter 0 xs
where insertAfter 0 xs = x : insertAfter n xs
insertAfter _ [] = undefined
insertAfter n xs = take n xs ++ (wrap n x (drop n xs))
,但使用示例:wrap 2'+'“ abcd”:wrap 2'+'“ abcd”:“ + ab + cd +” 我收到“ + ab + cd”,所以缺少“ +”。
答案 0 :(得分:2)
我可以随意更改传递给insertAfter
的参数。计数 down 常常比计数 up 更为方便,在这里也是如此。
wrap :: Int -> a -> [a] -> [a]
wrap _ _ [] = []
wrap n delim = insertAfter n
where
-- We've reached zero. So we insert the delimiter and
-- reset the counter to n.
insertAfter 0 xs = delim : insertAfter n xs
-- All done
insertAfter _ [] = ???
-- Still some work to do
insertAfter k (y : ys) = ???
顺便说一句:您所说的“合同”就是我们所说的类型签名。实际的合同通常会提供有关参数期望值和结果保证值的更多详细信息。例如,此处的合同将指定wrap
的第一个参数必须为正,并说明该函数的作用。
答案 1 :(得分:1)
您可以执行以下操作
wrap :: Int -> a -> [a] -> [a]
wrap _ _ [] = []
wrap n c cs | n == length cs = c:cs++[c]
| otherwise = c:x ++ wrap n c y
where (x,y) = splitAt n cs
n == length cs
条件是必需的,因为splitAt 2..n "a"
和splitAt 1 "a"
都给出("a","")
。我也总是假设n >= 1
。