-2

数値のリストを指定すると、各数値がその値と重複したリストを返す関数レプリケートを定義します。折り目を使用して、地図を作成し、

..>レプリケート[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]

これらの3つの関数がどのように比較されるかをもう少し明確にするために、ここにいくつかのスペースを追加しました。これらを見るとき、型変数、、は、、、、、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つと「内部」問題を持つ外部表現にキャストできますか?

于 2010-05-06T02:10:13.843 に答える
2

関数適用の順序がまちまちです。何ができる必要があるかを考えてください。

  1. 数字をそれ自体のコピーのnリストに変えるn
  2. リスト内のすべての番号に操作#1を適用します
  3. #2から取得したすべてのリストを連結します。

あなたは1を行う方法を知っています:take n $ repeat n
2と3のうち、どちらがamapでどちらがfold

ステップ2.はmap-リスト内のすべてのアイテムをリストにマッピング(「変換」)します。
ステップ3は、リスト要素の束を1つに集約(「フラット化」)しているfoldためです。

于 2010-05-06T02:08:08.470 に答える
1
replicate2 lst = concatMap(\x ->  (take x) (repeat x)) lst
于 2011-09-23T16:33:14.970 に答える
1
replicate xs = foldl (++) [] (map (\n->take n $ repeat n) xs) 

アイデアは、要素x、xをx回繰り返すだけのリストのすべての要素にマップすることです。次に、リストを折りたたんで連結します。リストが[5,1,2]であるとします。

(map (\n->take n $ repeat n) xs)[[5,5,5,5,5]、[1]、[2,2]]もそうです。そうすれば、内部リストを連結する必要があります。

于 2011-09-24T14:55:46.443 に答える