Result
Maybe
型は失敗するかもしれない単純な関数には役に立ちますが、 なぜ 失敗したかは教えてくれません。あなたのプログラムに何か問題があってコンパイラがNothing
としか言ってくれなかったらどうしましょうか?何が問題だったのか調べて運良く分かるといいですね!
こんなときResult
型が役に立ちます。Result
型は以下のように定義されます:
type Result error value
= Ok value
| Err error
この型のポイントは、問題が起こったときに問題が起こったということだけではなくさらなる情報を提供できるところにあります。この情報はエラーを通知したりエラーに対処したりするのにとても役に立ちます。
エラーを通知する
ひょっとしたら、我々は年齢を入力するサイトを持っているかもしれません。入力された年齢が無効な値ではないか以下のような関数で確認しましょう:
isReasonableAge : String -> Result String Int
isReasonableAge input =
case String.toInt input of
Nothing ->
Err "That is not a number!"
Just age ->
if age < 0 then
Err "Please try again after you are born."
else if age > 135 then
Err "Are you some kind of turtle?"
else
Ok age
-- isReasonableAge "abc" == Err ...
-- isReasonableAge "-13" == Err ...
-- isReasonableAge "24" == Ok 24
-- isReasonableAge "150" == Err ...
年齢を確認するだけではなく、ユーザに個々の入力に応じてエラーメッセージを表示することもできます。このようなフィードバックはただNothing
を返すよりとてもよいです。
エラーに対処する
Result
型はエラーに対処するのにも役に立ちます。役に立っている場所の1つとしてHTTPリクエストを作るところがあります。レフ・トルストイによる小説、 アンナ・カレーニナ の全文を表示したいとしましょう。これを表現しようとすると、HTTPリクエストは結果的にResult Error String
という型になります。この型はリクエストが成功して全文を得られるか、さまざまな理由で失敗するかを捕捉しています。
type Error
= BadUrl String
| Timeout
| NetworkError
| BadStatus Int
| BadBody String
-- Ok "All happy ..." : Result Error String
-- Err Timeout : Result Error String
-- Err NetworkError : Result Error String
ここでも先ほどの「エラーを通知する」の例でお見せしたようにより良いエラーメッセージを見せることができますが、それだけではなくエラーが起きたときの対処に使うこともできます。エラーがTimeout
だったら、少し待ってリクエストしなおせばうまくいくでしょう。一方BadStatus 404
だったらリクエストしなおす意味はないでしょう。
次の章では実際にHTTPリクエストの作り方を見せていきます。なのですぐさまResult
型とError
型に再会することになりますよ!