在这种情况下,Maybe 可能不够用:您需要担心三个条件:
- 用户没有输入任何内容
- 用户输入有效
- 用户输入无法解析
这个数据类型和函数直接表达了这一点:
data Input a = NoInput | Input a | BadInput String
deriving (Eq, Show)
input :: (Read a) => String -> Input a
input "" = NoInput
input s =
case filter (null.snd) (reads s) of
((a,_):_) -> Input a
otherwise -> BadInput s
请注意,它不是使用不完整的函数read,而是使用reads,这不会在无法转换的输入上出错。 reads 有一个有点尴尬的界面,唉,所以我几乎总是把它包装在一个返回 Maybe a 或类似的函数中。
使用示例:
> input "42" :: Input Int
Input 42
> input "cat" :: Input Int
BadInput "cat"
> input "" :: Input Int
NoInput
我会像这样编写你的 yearFilter 函数:
yearFilter :: Maybe Int -> Int -> Bool
yearFilter Nothing _ = True
yearFilter (Just x) y = x == objectYear y
然后我将用户输入处理为:
inputToMaybe :: Input a -> Maybe a
inputToMaybe (Input a) = Just a
inputToMaybe _ = Nothing
do
a <- input `fmap` getLine
case a of
BadInput s -> putStrLn ("Didn't understand " ++ show s)
otherwise -> ... yearFilter (inputToMaybe a) ....
注意:我已经稍微清理了yearFilter 中的代码:无需使用守卫从测试中生成布尔值 - 只需返回测试,函数应用程序 (objectYear) 绑定比运算符 (@ 987654333@) 所以去掉括号,用_替换未使用输入的名称。
好吧,我承认我情不自禁......我又重写了yearFilter,这次我更倾向于写它:
yearFilter :: Maybe Int -> Int -> Bool
yearFilter x y = maybe True (== objectYear y) x
了解 Maybe 和 maybe 是了解 Haskell 的第一件事,这让我真正爱上了这门语言。