Result型を使うと、関数は次のことをすべて示す単一の値を返せるようになります。
Result型は、2つの型を内部に持つジェネリック型です。
Result型はまた、次のようなケースを持つ[判別共用体][discriminated-union]です。
Ok <value>
Error <reason>
次の関数は、Resultの値を作る方法を示しています。
let validateName (name: string) : Result<string, string> =
match name with
| null -> Error "Name not found."
| "" -> Error "Name is empty."
| _ -> Ok name
この例では、Okの値は文字列(与えられた名前)で、Errorの値も文字列(エラーの原因を、人が読める形式で表したもの)です。
Resultの値の中身を読む次の型定義と関数シグネチャを見てみましょう。
type FileOpenError =
| NotFound
| AccessDenied
| FileLocked
let openFile (filename: string) : Result<int, FileOpenError> =
openFile関数を呼び出すコードは、次の例のように、パターンマッチングを使って成功と失敗のケースを処理できます。
match openFile(filename) with
| Ok handle -> doSomethingWithFile(handle)
| Error NotFound -> printfn $"Error: file {filename} was not found."
| Error AccessDenied -> printfn $"Error: you do not have permission to open the file {filename}."
| Error FileLocked -> printfn $"Error: file {filename} is already in use."
この演習では、パスワードチェッカーを作成します。 パスワードチェッカーは、ユーザーが設定しようとしているパスワードを検証し、対象のリソースへのアクセスを管理する組織が定めた一連の要件を満たしていることを確認します。
この演習では、パスワードの要件は次のとおりです。
解答では、成功か失敗かの状態をResultで表す必要があります。
成功の場合、Resultは検証済みのパスワードを文字列として伝える必要があります。
失敗の場合、Resultは違反したルールを伝える必要があります。
この演習のパスワードチェッカーは簡易的なものです。違反したルールが1つだけの場合にのみ示します。 後続の演習では、複数のルールに同時に違反した場合を示せる、より現実的なパスワードチェッカーを扱います。
checkPassword関数を実装してくださいcheckPassword関数は、与えられたパスワードを前述のルールに照らしてチェックします。失敗した場合は、PasswordRuleの値のいずれかを結果の値に含めることで、違反したルールを示します。
checkPassword "abcdefghij5#"
// => Error MissingUppercaseLetter
getStatusMessage関数は、checkPasswordから返された結果の意味を示す、人間が読めるメッセージを含む文字列を返します。
getStatusMessage (Error MissingDigit)
// => "Error: does not have at least one digit"