-2

定义一个函数 replicate ,它给定一个数字列表,返回一个列表,每个数字都复制其值。使用折叠、映射和拍摄

..> 复制 [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]

我已经使用列表理解和递归解决了这个问题:

replicate2 [] = []
replicate2 (n:nn) = take n(repeat n) ++ replicate2 nn

但是你将如何使用 fold 和 map 来做到这一点?到目前为止我有: 复制 n = map (foldl1 (take n(repeat n)) n) n 这显然是错误的,但我认为我很接近..

所以任何帮助都会很好,谢谢!

4

4 回答 4

6

Haskell 中的关键始终遵循以下类型

foldr  :: (a -> b -> b) -> b -> [a] -> b
foldr1 :: (a -> a -> a)      -> [a] -> a
map    :: (a -> b)           -> [a] -> [b]
take   :: Int                -> [a] -> [a]

我在这里添加了一些空格,以便更清楚地比较这三个函数的比较。请记住,当您查看这些时,类型变量aorb可以匹配任何类型,包括String, or [Float], 甚至[(String,[Int])]. 例如,在表达式中:

foldr (\a b -> product a + b) (0::Int) [[1,2,4],[5,2],[0,3,6]]

foldr被用作 type ([Int] -> Int -> Int) -> Int -> [[Int]] -> Int。那就是a已经匹配[Int]b已经匹配Int

现在:从“最外层”的层面思考你的表情必须做什么。这些函数中的哪一个适合这种形式?

您能否将您的问题转换为具有这些形式之一和“内部”问题的外部表达式?

于 2010-05-06T02:10:13.843 回答
2

您的功能应用程序顺序混淆了。想想你需要能够做什么:

  1. 将数字转换为自身副本的n列表n
  2. 对列表中的每个数字应用操作 #1
  3. 将您从 #2 获得的所有列表连接在一起。

你知道怎么做 1:take n $ repeat n
在 2 和 3 中,哪个是 amap哪个是 a fold

第 2 步是map- 您正在将列表中的每个项目映射(“转换”)到一个列表中。
步骤 3. 是 a fold,因为您将一堆列表元素聚合(“展平”)为一个。

于 2010-05-06T02:08:08.470 回答
1
replicate xs = foldl (++) [] (map (\n->take n $ repeat n) xs) 

The idea is map on every element of a list which just repeats an element x , x number of times. Then fold on the list to concatenate it. Suppose the list is [5,1,2]

So (map (\n->take n $ repeat n) xs) is [[5,5,5,5,5],[1],[2,2]] and then you just have to concatenate the inner lists.

于 2011-09-24T14:55:46.443 回答
1
replicate2 lst = concatMap(\x ->  (take x) (repeat x)) lst
于 2011-09-23T16:33:14.970 回答