为什么这段代码不起作用?如果string是一个数字,我想返回Bool.
isNumber = do
n <- getLine
let val = case reads n of
((v,_):_) -> True
_ -> False
Run Code Online (Sandbox Code Playgroud)
Don*_*art 16
首先,您有语法错误:
A.hs:3:5:
The last statement in a 'do' construct must be an expression:
let val
= case reads n of {
((v, _) : _) -> True
_ -> False }
Run Code Online (Sandbox Code Playgroud)
因为您的函数尚未返回值.修复:
isNumber = do
n <- getLine
let val = case reads n of
((v,_):_) -> True
_ -> False
return val
Run Code Online (Sandbox Code Playgroud)
现在它在语法上是正确的,但它有一个类型错误:
A.hs:3:20:
Ambiguous type variable `a0' in the constraint:
(Read a0) arising from a use of `reads'
Probable fix: add a type signature that fixes these type variable(s)
Run Code Online (Sandbox Code Playgroud)
为什么?因为read超载了.所以编译器不知道你要读什么.在这种情况下,您正在尝试读取数字.让我们说,一个Integer:
isNumber :: IO Bool
isNumber = do
n <- getLine
let val = case (reads :: ReadS Integer) n of
((v,_):_) -> True
_ -> False
return val
Run Code Online (Sandbox Code Playgroud)
不过,它并不是真正的惯用语.让我们将IO与纯代码分开,并实际返回解析后的数字,如果成功的话:
readNumber :: String -> Maybe Integer
readNumber s = case reads s of
((v,_):_) -> Just v
_ -> Nothing
getNumber :: IO (Maybe Integer)
getNumber = do
s <- getLine
return (readNumber s)
Run Code Online (Sandbox Code Playgroud)
测试:
*Main> getNumber
123
Just 123
*Main> getNumber
dons
Nothing
Run Code Online (Sandbox Code Playgroud)
因此,我们已经清理了解析,并从解析中分离了IO,这意味着您可以单独测试解析器,并添加类型信息来记录您的设计.