2011-12-10 12 views
1

私はfindIndicesと基本的に同じですが、再帰的な方法で関数を書くことが任されています。これまでのところ、私はこれを作るために管理している:再帰findIndices

getIndicesFor :: (a -> Bool) -> [a] -> [Int] 
getIndicesFor x (y:ys) = (fst (head(filter ((x y).snd) as))):getIndicesFor x ys where 
    as = (zip [0..] (y:ys)) 

しかし、これは言ってエラーになります:「Could'tマッチ期待タイプb0 -> Bool' with actual typeブール」」。そして私は問題を理解しているようには見えません。

ご回答ありがとうございます。

答えて

1

この関数によって何の再帰的な定義方法getIndicesFor直接

書き換えを=(郵便番号[0 ..] XS)としての用途を持っていない場合do表記を使って書くことができます。それが明示的な再帰を使用していないので、あなたはおそらく、答えとしてこのを提出するための信用を得ることはありませんので、私はこれを提示し、悪い感じていない:

import Control.Monad (guard) 

getIndicesFor :: (a -> Bool) -> [a] -> [Int] 
getIndicesFor f xs = do 
    (n, x) <- zip [0..] xs 
    guard (f x) 
    return n 

-- in fact you could write it compactly as a list comprehension 
-- though I personally avoid list comprehensions, as I find "do" syntax clearer 
-- getIndicesFor f xs = [n | (n, x) <- zip [0..] xs, f x] 

テスト...

ghci> take 5 $ getIndicesFor even [0 ..] 
[0, 2, 4, 6, 8] 
ghci> take 5 $ getIndicesFor even [2, 4 ..] 
[0,1,2,3,4] 

コンセプトはシンプルなので、そうですか?リストから要素を選択し、指定された関数でそれをテストし、その索引が合格するとリストにその索引を追加します。

明示的な再帰を使用してこの関数を記述する必要がある場合、この2つのケースを別々に処理する必要があります。この特定の要素はテストに合格するか失敗しますか?合格した場合は、インデックスを結果リストに追加します。失敗した場合は、は表示されません。これはあなたのコードで今見ている主な問題です。

getIndicesFor x (y:ys) = blahblah : getIndicesFor x ys 

あなた常にテストに失敗したかどうかをyパスや、何かを追加します。これは間違っています。 2つの異なるケースを区別するには、ifまたはcaseステートメントを使用してください。明示的な再帰を使用している場合も、あなたは明示的に空のリストのケースを処理する必要があります。

getIndicesFor x [] = ??? 
3

タイプエラーが見えると思います。あなたはタイプ(Int, a) -> Boolを有するべきであるフィルタリング機能、として表現

((x y).snd) 

を使用しています。ただし、

x :: a -> Bool 
y :: a 

となると、(x y) :: Boolとなります。しかし、sndに投稿を投稿してフィルタリング機能を構築しようとしています。フィルタリング機能は、タイプがsomething -> Boolの場合にのみ機能します。それは、エラーメッセージが何を揺さぶっているのかです。

yが調査対象のリストの要素の1つにすぎない場合、なぜフィルタリング機能を構築するのにyを使用するのかはわかりません。いずれにしても、なぜあなたがリストを壊す必要があるのか​​はわかりません。(y:ys)

あなたの試行にはかなりの論理がありますが、「配管」作業が必要です。フィルタリング機能をソートしたら、filterの出力を処理して、必要なデータを取得する方法を調べる必要があります。

私がこのプログラムを書いていたのであれば、私は真剣にlist comprehensionsの使用を検討したいと思います。見たことがないなら、それをチェックする価値があります。

+0

私は申し訳ありませんが、おそらく全体の質問に変化するように、私は、findIndicesとelemIndicesを混同しています。再帰的な関数を作るときにそれをするように教えられたので、私が(y:ys)としてリストを壊した理由があります。 –

2

注意事項あなたはelemIndicesと同じ機能を記述する必要がある場合は

  • することは、あなたのgetIndicesForは同じシグネチャfilter ((x y).snd)を見てみると:: Eq a => a -> [a] -> [Int]

  • を持つ必要があります。 2番目の要素がxに等しいペアをフィルタリングするように思えます。二組の要素は、我々は2回使用(\tuple -> snd tuple == x)

  • (y:ys)のようなラムダ関数を使用する場合がありますので、あなたは[email protected](y:ys)を使用して、listの代わり(y:ys)それを呼び出すことができますxに等しいことを考え出します。

  • 角括弧の代わりに$を使用することをお勧めします。

  • 再帰関数を定義するときは、空のリストの大文字と小文字を一致させることを忘れないようにしてください。

  • head機能に注意してください。これは、list-argumentが空の場合にエラー例外を返すことがあるため、安全ではありません。[*** Exception: Prelude.head: empty list

  • 現在の状態では、関数は(fstを使用しているため)、インデックスを返しません。そして実際には、のインデックス(y:ys)のインデックスは元のリストのその要素のインデックスと異なる場合があります。

+0

申し訳ありませんがfindIndicesとelemIndicesが混在しているので、おそらく全体の質問が変わります。 –

+0

'getIndeciesFor'は、要素が「正しい」かどうかを決定する任意の関数をとるため、' Eq'制約は不要です。しかし、彼はそれを 'x'と名付けているので、混乱します。 –

-2
getIndicesFor :: (a -> Bool) -> [a] -> [Int] 
getIndicesFor f xs = map fst (filter (f.snd) as) 
    where 
     as = zip [0..] xs 

あなたが使用ヘルパー関数

getIndicesFor :: (a -> Bool) -> [a] -> [Int] 
getIndicesFor f xs = aux as 
    where 
     as = zip [0..] xs 
     aux [] = [] 
     aux (x:xs) = 
     if (f.snd) x then 
      (fst x) : aux xs 
     else 
      aux xs 
+0

おそらく宿題に少し役立つでしょうか? – pigworker

+0

これがわからない場合は、再帰的定義のポリシーの問題は考えられないかどうか答えてください。そのような関数をフォーム内で定義するには、再帰的な形で再記述するかどうかを検討することをお勧めします。再帰的なフォームを書き換えるには、ヘルパー関数が必要なようです。 – BLUEPIXY