2011-09-19 3 views
8

私はハスケルと闘争しています。再帰を使って物事を繰り返すという考え方です。例えばこのスニペットはどのようにハスケルに変換されますか?

、どのよう

// this might seem silly but I need to do it 
list1 = empty list 
list2 = list of numbers 
for i from 0 to N // N being a positive integer 
    for each number in list2 
     if number == i, add to list1 

は、 '機能的なパラダイム' に変換しますか?どんな指導も高く評価されます。

答えて

9

ステップバイステップで行く:与えられたとして、私たちはこれを取るよ

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の値を渡す必要があります。再帰がどこにあるか、両方がfilterfoldl私たちのためにそれをやっている

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は、我々は左倍のために必要なものを正確に折るまさにです。経験則として、それを行うためのより高いレベルの関数がある場合は、通常は直接再帰を避けるほうがよいでしょう。


言った、ここでアルゴリズムは、複数の方法で愚かであるが、それはそれが役立つだろうより多くのあなたの実際の質問から気をそらすでしょうようにそれが見えたので、私はそれに取得する必要はありませんでした。

+0

明示的連結ステップで折りたたむ代わりに 'concatMap'を使用してみませんか? – bdonlan

+2

この場合、リスト内包表記を使用することができます。[number | i < - [1..N]、number <-list2、i == number>これは疑似コードの直接変換です。 – ysdx

+0

すばらしい答えをありがとう。私が投稿したスニペットが奇妙であることに気がついた...私はそれからどんな意味合いも大幅に削った。私がやっている基調講習の一環です。 –

10

申し訳ありませんが、私は助けることが、より良いアルゴリズムを使用することはできません...

let goodNumber n = (0 <= n && n < N) 
let list1 = sort (filter goodNumber list2) 

編集:OPが実装しようとしていたので、これはやり過ぎの少しは、ある後知恵で最初にアルゴをソートする。

0
let list1 = sort [a | a<-list2, a>=0, a<=N] 

a<-list2をピックアップリスト2の各番号は a>=0, a<=Nチェックが選んだ数は、条件が満たされた場合、aはリスト2のすべての要素は、このように確認されたら、新しいリスト に入れている これらすべての条件を満たしている場合新しいリストを作成すると、これを並べ替えます 結果リストがリスト1に割り当てられます

関連する問題