你如何使用折叠图解决这个Haskell问题并采取?

时间:2010-05-06 01:47:24

标签: haskell higher-order-functions

定义一个函数复制,给定一个数字列表返回一个 列表与每个数字重复其值。使用折叠,地图和

..>复制[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 这显然是错的,但我认为我很接近......

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

4 个答案:

答案 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]

我在这里添加了一些空格,以便更清楚地了解这三个函数的比较。请记住,当您查看这些类型变量时,ab可以匹配任何类型,包括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)

您的功能应用程序订单已混淆。 想想你需要做什么:

  1. 将数字n转换为n自身副本列表
  2. 对列表中的每个号码应用操作#1
  3. 连接#2中的所有列表。
  4. 你知道怎么做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]] 然后你只需要连接内部列表。