Result 类型让函数可以返回一个值,同时表明以下几件事:
Result 类型是一种泛型类型,包含两种底层类型:
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必须给出失败时被违反的那条规则。
在本练习中,密码检查器会非常简化,它只会在有一条规则被违反时给出提示。 后续的练习会探讨一个更贴近现实的密码检查器,它可以同时指出多条被违反的规则。
checkPassword函数checkPassword函数会根据上述规则检查给定的密码。检查失败时,它会把某个PasswordRule值封装在结果值中,以此来指出被违反的规则。
checkPassword "abcdefghij5#"
// => Error MissingUppercaseLetter
getStatusMessage函数会返回一个字符串,其中包含一条人类可读的消息,说明checkPassword所返回结果的含义。
getStatusMessage (Error MissingDigit)
// => "Error: does not have at least one digit"