定义一个函数复制,给定一个数字列表返回一个 列表与每个数字重复其值。使用折叠,地图和
..>复制[5,1,3,2,8,1,2]
输出:[5,5,5,5,5,1,3,3,3,2,2,8,8,8,8,8,8,8,8,1,2,2]
我已经使用List comprehension和recursion来解决这个问题:
replicate2 [] = []
replicate2 (n:nn) = take n(repeat n) ++ replicate2 nn
但你如何使用折叠和地图来做到这一点? 到目前为止我有:复制n = map(foldl1(取n(重复n))n)n 这显然是错的,但我认为我很接近......
所以任何帮助都会很好,谢谢!
答案 0 :(得分:6)
Haskell中的密钥总是遵循类型:
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr1 :: (a -> a -> a) -> [a] -> a
map :: (a -> b) -> [a] -> [b]
take :: Int -> [a] -> [a]
我在这里添加了一些空格,以便更清楚地了解这三个函数的比较。请记住,当您查看这些类型变量时,a
或b
可以匹配任何类型,包括String
或[Float]
等内容,甚至[(String,[Int])]
。例如,在表达式中:
foldr (\a b -> product a + b) (0::Int) [[1,2,4],[5,2],[0,3,6]]
foldr
被用作([Int] -> Int -> Int) -> Int -> [[Int]] -> Int
类型。这是a
已匹配[Int]
而b
已匹配Int
。
现在:在“最外层”层面思考你的表达必须做什么。这些功能中的哪一个适合这种形式?
你可以将问题转换为具有这些形式之一和“内在”问题的外部表达式吗?
答案 1 :(得分:2)
您的功能应用程序订单已混淆。 想想你需要做什么:
n
转换为n
自身副本列表你知道怎么做1:take n $ repeat n
2和3中的哪一个是map
并且是fold
?
第2步是map
- 您将映射(“转换”)列表中的每个项目放入列表中。
第3步是fold
,因为您将聚合(“展平”)一堆列表元素合并为一个。
答案 2 :(得分:1)
replicate2 lst = concatMap(\x -> (take x) (repeat x)) lst
答案 3 :(得分:1)
replicate xs = foldl (++) [] (map (\n->take n $ repeat n) xs)
这个想法是在列表的每个元素上映射,它只重复元素x,x次。然后在列表上折叠以连接它。假设列表是[5,1,2]
所以(map (\n->take n $ repeat n) xs)
是[[5,5,5,5,5],[1],[2,2]]
然后你只需要连接内部列表。