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

发布于 2024-11-08 17:45:11 字数 195 浏览 3 评论 0原文

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

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

Why this code doesn't work ? I would like to return Bool if string is a number.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

勿忘初心 2024-11-15 17:45:11

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

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 与解析分开,这意味着您可以单独测试解析器,并添加类型信息记录您的设计。

Firstly, you have a syntax error:

A.hs:3:5:
    The last statement in a 'do' construct must be an expression:
    let val
          = case reads n of {
              ((v, _) : _) -> True
              _ -> False }

Because your function doesn't return a value yet. Fixing that:

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

Now it is syntactically correct, but it has a type error:

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)

Why? Because read is overloaded. So the compiler doesn't know what you're trying to read. In this case, you're trying to read a number. Let's say, an Integer:

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

Still, its not really idiomatic. Let's separate the IO from the pure code, and actually return the parsed number, if it succeeds:

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)

Testing:

*Main> getNumber 
123
Just 123
*Main> getNumber 
dons
Nothing

So we've cleaned up the parsing, and separted IO from parsing, meaning you can test your parser in isolation, and added type information to document your design.

失与倦" 2024-11-15 17:45:11

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

编写一个单独的类型 < 的纯函数也是一个好主意 。代码>字符串-> Bool 并在不纯的 IO 代码中使用它。

Add return val or simply write return $ case .... The last statement in do ... must be an expression. In your particular case it must be an expression of type IO Bool, so you need to lift value into IO monad with return function. You also need to specify type for v explicitly (you will probably need ScopedTypeVariables GHC extension for this.)

It is also a good idea to write a separate pure function of type String -> Bool and use it in the impure IO code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文