2

私はHaskellでプログラムすることを自分自身に教えており、検索機能に取り組んでいます。"hello"これは、となどの2つの文字列を取り、に表示される"he"回数をカウントします。"he""hello"

検索関数は、単語がリストで見つかった回数など、関数の開始時に入力する必要のないいくつかのことを追跡する必要があります。そこで、関数を2つの小さな関数に分割しました。1つはユーザーが最初にデータを入力し、次にデータを2番目の関数に転送して作業を行います。

これが私のコードです:

search :: (Eq a) => [a] -> [a] -> Integer
search [] _ = 0
search _ [] = 0
search x y = search1 x y y 0

search1 :: (Eq a) => [a] -> [a] -> [a] -> Integer -> Integer
search1 _ _ [] n = n
search1 x [] z n = search1 x z z (n+1)
search1 [] _ _ n = n
search1 (x:xs) (y:ys) z n
  | x == y = search1 xs ys z n
  | otherwise = search1 xs (y:ys) z n

search1その中で、ユーザーが入力するために冗長になるデータを必要とする関数から始める代わりに、ユーザーのためsearchにデータを「プラグイン」する関数を作成しsearch1ました。

私の質問は、冗長データを「プラグイン」する関数をHaskellで作成することは良い習慣ですか?それとも私は何か違うことをすべきですか?

4

1 に答える 1

7

はい、それは良い習慣です。ただし、2番目の関数をそれ自体では役に立たず、他の関数のワーカーとしてのみ機能する場合は、2番目の関数を最初の関数に対してローカルにする方がよい場合がよくあります。

ラッパーのローカルにワーカーを作成する場合、ワーカーに引数として渡すことなく、ワーカーの本体でラッパーの引数を参照できます。これにより、パフォーマンスが向上することがよくあります。

たとえば、ローカルワーカーを使用した関数は次のようになります。

search :: (Eq a) => [a] -> [a] -> Integer
search [] _ = 0
search _ [] = 0
search hay needle = search1 hay needle 0
  where
    search1 x [] n = search1 x needle (n+1)
    search1 [] _ n = n
    search1 (x:xs) (y:ys) n
      | x == y = search1 xs ys n
      | otherwise = search1 xs (y:ys) n

ここで、再帰呼び出しで変更されなかったワーカーの1つの引数を削除しました。また、ワーカーをローカルにすることで、空のをチェックする必要がなくなりますneedle

于 2012-05-15T20:29:35.477 に答える