Parsing 读取字符串并测试它是否为数字

Parsing 读取字符串并测试它是否为数字,parsing,haskell,io,Parsing,Haskell,Io,为什么这个代码不起作用?如果字符串是一个数字,我想返回Bool isNumber = do n <- getLine let val = case reads n of ((v,_):_) -> True _ -> False 首先,您有一个语法错误: A.hs:3:5: The last statement in a 'do' construct must be an expressio

为什么这个代码不起作用?如果字符串是一个数字,我想返回Bool

isNumber = do
    n <- getLine
    let val = case reads n of
                ((v,_):_) -> True
                _ -> False

首先,您有一个语法错误:

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
为什么??因为read是重载的。所以编译器不知道你想读什么。在这种情况下,您试图读取一个数字。比如说,一个整数:

因此,我们已经清理了解析,并将IO与解析分离,这意味着您可以单独测试解析器,并添加类型信息来记录您的设计。

添加return val或简单地编写return$case。。。。do中的最后一个语句。。。必须是一个表达式。在您的特定情况下,它必须是IO Bool类型的表达式,所以您需要使用返回函数将值提升到IO monad中。您还需要显式地指定v的类型。为此,您可能需要ScopedTypeVariables GHC扩展


编写一个单独的纯函数,类型为String->Bool,并将其用于不纯IO代码也是一个好主意。

如果您还没有读过它,这里有一个链接指向一个非常好的Haskell教程:我想知道是真是假,你的代码不幸地返回了我的数字或什么都没有。你可以使用isJust函数将一个Maybe转换成Bool。例如,isJust getNumber。所以我需要3个函数:readNumber、getNumber和isJust-函数太多了-我只需要一个-所以我需要其他解决方案。我的帖子的重点是向你展示如何将问题分解为三个部分,然后你可以将它们组合成一个能正确完成工作的函数。您的单个函数就是这三个独立函数的组合:getLine、readNumber和isJust。像这样分段构建代码是一种很好的开发实践。但是,如果出于某种原因,您不想习惯地这样做,那么最后一个版本的isNumber实际上会完全满足您的需要。这只是一个丑陋的代码。
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)
isNumber :: IO Bool
isNumber = do
    n <- getLine
    let val = case (reads :: ReadS Integer) n of
                ((v,_):_) -> True
                _         -> False
    return val
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