为什么这段代码不起作用?如果string是一个数字,我想返回Bool.
isNumber = do
    n <- getLine
    let val = case reads n of
                ((v,_):_) -> True
                _ -> False
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 }
因为您的函数尚未返回值.修复:
isNumber = do
    n <- getLine
    let val = case reads n of
                ((v,_):_) -> True
                _         -> False
    return val
现在它在语法上是正确的,但它有一个类型错误:
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)
为什么?因为read超载了.所以编译器不知道你要读什么.在这种情况下,您正在尝试读取数字.让我们说,一个Integer:
isNumber :: IO Bool
isNumber = do
    n <- getLine
    let val = case (reads :: ReadS Integer) n of
                ((v,_):_) -> True
                _         -> False
    return val
不过,它并不是真正的惯用语.让我们将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)
测试:
*Main> getNumber 
123
Just 123
*Main> getNumber 
dons
Nothing
因此,我们已经清理了解析,并从解析中分离了IO,这意味着您可以单独测试解析器,并添加类型信息来记录您的设计.