4

私はYesodとHaskellを初めて使用するので、我慢してください。ただし、ファイルを受け入れ、単語をカウントして、新しいYesodWebページに結果を表示するプログラムがあります。例外をより適切にキャッチする方法が必要です。たとえば、隠しファイルで以下の関数を実行する場合:

wordCount :: String -> String -> String

wordCount ('.' : _) _   = error "Cannot count hidden files."
wordCount name contents = "<p>There are <b>" ++ show (length $ words contents) ++ "</b> words in your file <i>" ++ name ++ "</i>.</p>"

そのエラーメッセージを表示してから、ユーザーが新しいファイルを送信するためのフォームを表示したいと思います。現在、「ページの読み込み中にサーバーへの接続がリセットされました」というページに移動します。

Yesodには独自のcatch関数のセットがあり、自分で作成するには非表示にする必要があると思いますが、それらがどこにあるかわからず、ドキュメントでそれらへの参照を見つけることができません。ユーザーが悪いファイルを入れた場合にサイトがクラッシュすることは望ましくありません。

どんな助けでも本当にありがたいです。

編集:提案をありがとう。この方法でエラーをスローすることはエラーに対処するための最良の方法ではないことを私は理解していますが、問題は実際には、Yesodサイトではなくターミナルから通常実行される既存のHaskellコードで作業していることです。小さな例として単語数を使用しましたが、実際には、数十の関数と散在するエラースローを含む数十のファイルです。うまくいけば、既存のコードのすべての関数を完全に変更することなく、これらをキャッチできます。Yesodで例外をキャッチする方法について誰かが何か提案があれば、私は本当にそれをいただければ幸いです。

4

1 に答える 1

3

errordflemstr が言ったように、そのような回復可能なエラーには使用しないでください。エラー メカニズムは -- に似てundefinedいます。これは、まだ記述されていない関数や無限ループなど、完全に壊滅的なエラーを表します。悪いケースに決して遭遇しないと予想される部分関数には問題ありませんが、予期されて処理する必要があるエラーには最適ではありません。さらに、型システムは の使用を反映していないerrorため、関数の消費者はエラーをキャッチする方法を知りません。

代わりに、このようなエラーを表すMaybeorのような型を使用する必要があります。Eitherたとえば、この関数を次のように書き換えることができます。

wordCount :: String -> String -> Maybe String
wordCount ('.' : _) _   = Nothing
wordCount name contents = Just $ "<p>There are <b>" ++ show (length $ words contents) ++ "</b> words in your file <i>" ++ name ++ "</i>.</p>"

ここで、 aStringを返す代わりに、 a を返しますMaybe StringNothingこれは、またはのいずれかで実行できるタイプですJust String。はNothing失敗を表します。つまり、入力が無効だったために関数が失敗しました。はJust成功を表します。

次に、エラーを「キャッチ」するには、パターン マッチのみを使用できます。

case wordCount fileName contents of
  Just res -> res
  Nothing  -> "Cannot count hidden files!"

Data.Maybeには、一般的なケースでコードをより簡潔にするための便利な関数もいくつかあります。

別のオプションはEitherタイプです。Maybe型では、コンストラクNothingターは追加情報を持ちません。あなたが知っているのは、関数が失敗したということだけです。Either「失敗」の場合任意の追加情報を運ぶことを除いて、同じように動作します。「失敗」のケースが呼び出されLeft、「成功」のケースが呼び出されRightます。この型には、エラー情報の型と結果の型の 2 つのパラメーターもあります。次のようになります。

wordCount :: String -> String -> Either String String
wordCount ('.' : _) _   = Left "You cannot count a hidden file!"
wordCount name contents = Right $ "<p>There are <b>" ++ show (length $ words contents) ++ "</b> words in your file <i>" ++ name ++ "</i>.</p>"

その後、結果を a と同じ方法で処理できますMaybeMaybeこの場合、関数が失敗する方法は 1 つしかないため、a が望ましいと思います。考えられるエラー条件が多数ある場合はEither、より良い賭けになります。

于 2012-07-23T19:58:30.337 に答える