は、すべてはあなたの言語について何かを教えるいくつかのオプションがあります。 まず第一に、イプシロンハルが記載されているという問題があります。今のところ、私はコードにエラーを投げるだけです。
maximumOddError :: a
maximumOddError = error "maximumOdd: list contains no odd element"
最も重要な問題は、開始時に奇数があるかどうかわからないことです。だから、あなたはそのテストを延期しなければなりません(私たちはそれに来るでしょう)か、フィルターをかけて一度にチェックインする必要があります。
オプション1:末尾再帰
最も簡単な解決策は一つに両方のチェックを行うことです。一般的に、これは最適な最適化手法です。今のところ、エラー処理と反復が分かれています。
maximumOdd :: (Integral a) => [a] -> a
maximumOdd ls = case dropWhile even ls of
[] -> maximumOddError
n:ns -> findOddMax n ns -- n is definitely odd
where
findOddMax currentMax [] = currentMax
findOddMax currentMax (x:xs)
| even x = findOddMax currentMax xs
| x < currentMax = findOddMax currentMax xs
| otherwise = findOddMax x xs
はオプション2:ソート
代わりのすべての部分を見て、あなたはまた、高レベルの視点を取ることができます。検索する理由は、リストをソートして検索する要素を一方の端に表示させることができるときです。もちろんフィルタリングしなければならないので、基本的にはlast . sort . filter odd
のようなものです。それは降順でリストをソートする方が良いですので、しかしlast
は、別のトラバースです:head
は空のリストに失敗すること
import Data.List (sortBy)
maximumOdd :: (Integral a) => [a] -> a
maximumOdd = head . sortBy reverseOrder . filter odd
where
reverseOrder a b = compare b a
注意。したがって、エラー処理はあまり良くありません。しかし、それは簡単に追加する必要があります。どのような性能は単純なものと比べて何ですか?maximum . filter odd
?教えてください!
オプション3:
を扱う素敵なエラーで末尾再帰は、今のMaybe
を経由して、いくつかの優れたエラー処理を追加してみましょう。それを行う最も簡単なバージョンは、テールの再帰的なバージョンです。エラー処理と反復を分離しています。
maximumOdd :: (Integral a) => [a] -> Maybe a
maximumOdd ls = case dropWhile even ls of
[] -> Nothing
n:ns -> Just $ findOddMax n ns -- n is definitely odd
where
findOddMax … -- same as above
これは非常にdfeuer年代と同じ方法です。彼は、既存の関数をより短く効率的にするために、より多くの既存の関数を使用しました。そして、エラー処理を再帰に統合しました。これが、Haskellのプログラマーが最も経験したことです。 (あなたは、ラッピングとアンラッピングのパフォーマンスコストについて議論が、えっ可能性があり、あなたがそれを必要とするときがあることを行う。。)
オプション4:
を扱う素敵なエラーでソートをこの1つは、同様に簡単です、素敵がありますので、バージョンhead
が必要です。
import Data.Maybe (listToMaybe)
maximumOdd :: (Integral a) => [a] -> Maybe a
maximumOdd = listToMaybe . sortBy reverseOrder . filter odd
where
reverseOrder a b = compare b a
オプション5:最後に
を扱う素敵な誤りとの直接トラバーサル、我々は戻って最初のアプローチにしています。しかしMaybe
ではエラーチェックを延期できます。事は:あなたはいくつかの特別なツールを知る必要がある、またはそれらを発明しなければならない。私はちょうど既存のものを使用します。
import Control.Applicative ((<|>))
maximumOdd :: (Integral a) => [a] -> Maybe a
maximumOdd [] = Nothing
maximumOdd [x] | even x = Nothing
| otherwise = Just x
maximumOdd (x:xs) | even x = maximumOdd xs
| otherwise = max x <$> maximumOdd xs -- either "max x" applied inside the Maybe-construct
<|> Just x -- or x, if that produced an error
'maximumOdd = maximum。フィルタ奇数 ' – Alec
型制約を 'Ord a => a'から' Integral a => a'に変更する必要があることに注意してください。 – mnoronha
@mnoronhaええ、 'odd'の存在は' Integral'型を意味します –