ステップバイステップで行く:与えられたとして、私たちはこれを取るよ
list2 = list of numbers
を、そうlist2
はまだ数字のリストだけです。
for i from 0 to N // N being a positive integer
Haskellでこれを行うための正しい方法は、リストで一般的です。怠惰は、値が使用されたときにだけ計算されることを意味します。したがって、0からNまでのリストをトラバースすると、ここにあるループと同じことになります。だから、ちょうど[0..n]
がそのトリックを行います。私たちはそれをどうするかを理解する必要があります。考える
for each number in list2
「の各」私たちはここにlist2
の全体を横断する必要がありますことを推測することができます。私たちはそれで何をするのか、私たちはまだ分かりません。
if number == i, add to list1
私たちが行くように私たちはlist1
を構築しているので、理想的に我々はそれが、式の最終的な結果になりたいです。つまり、それぞれの再帰的ステップでは、結果がの "これまでのところ"になるようにします。そのためには、各ステップの結果を確実に伝える必要があります。だから、
、それの肉に降りる:
filter
機能は、いくつかの述語に一致する、リスト内のすべての要素を検索します。ここではfilter (== i) list2
を使用して後にあるものを見つけて、前のステップの結果に追加します。したがって、各ステップは次のようになります。
step :: (Num a) => [a] -> a -> [a]
step list1 i = list1 ++ filter (== i) list2
これは内部ループを処理します。外側に戻って、リストから各値i
に対してこれを実行し、各ステップでlist1
の値を渡す必要があります。再帰がどこにあるか、両方がfilter
とfoldl
私たちのためにそれをやっている
list2 :: (Num a) => [a]
list2 = -- whatever goes here...
step :: (Num a) => [a] -> a -> [a]
step list1 i = list1 ++ filter (== i) list2
list1 :: (Num a) => a -> [a]
list1 n = foldl step [] [0..n]
あなたが迷っている場合:これは、関数が用であり、この場合にはstep
は、我々は左倍のために必要なものを正確に折るまさにです。経験則として、それを行うためのより高いレベルの関数がある場合は、通常は直接再帰を避けるほうがよいでしょう。
言った、ここでアルゴリズムは、複数の方法で愚かであるが、それはそれが役立つだろうより多くのあなたの実際の質問から気をそらすでしょうようにそれが見えたので、私はそれに取得する必要はありませんでした。
明示的連結ステップで折りたたむ代わりに 'concatMap'を使用してみませんか? – bdonlan
この場合、リスト内包表記を使用することができます。[number | i < - [1..N]、number <-list2、i == number>これは疑似コードの直接変換です。 – ysdx
すばらしい答えをありがとう。私が投稿したスニペットが奇妙であることに気がついた...私はそれからどんな意味合いも大幅に削った。私がやっている基調講習の一環です。 –