从命令行util读取字符串可以“读取”#39;作为一个浮动

时间:2015-11-07 18:48:28

标签: haskell

我试图编写提示用户输入Float的代码,并在输入有效的float之前继续这样做。

我尝试过以下方法:

getFloat :: Float
getFloat = do 
    input <- getLine
    case (readMaybe input :: Maybe Float) of Just f -> f
                                             Nothing -> do getFloat

但我收到以下错误:

Main.hs:41:5:
    Couldn't match type `IO b0' with `Float'
    Expected type: IO String -> (String -> IO b0) -> Float
      Actual type: IO String -> (String -> IO b0) -> IO b0
    In a stmt of a 'do' block: input <- getLine
    In the expression:
      do { input <- getLine;
           case (readMaybe input :: Maybe Float) of {
             Just f -> f
             Nothing -> do { ... } } }
    In an equation for `getFloat':
        getFloat
          = do { input <- getLine;
                 case (readMaybe input :: Maybe Float) of {
                   Just f -> f
                   Nothing -> ... } }

Main.hs:42:56:
    Couldn't match expected type `IO b0' with actual type `Float'
    In the expression: f
    In a case alternative: Just f -> f

Main.hs:43:60:
    Couldn't match expected type `IO b0' with actual type `Float'
    In a stmt of a 'do' block: getFloat
    In the expression: do { getFloat }

我是初学者,如果有人能解释我在这里失踪的内容,我将非常感激。

2 个答案:

答案 0 :(得分:2)

对于Just case,请使用-> return f代替-> f

然后只删除getFloat的类型签名。编译完成后,让ghci告诉你getFloat的类型签名是什么。

完整代码:

getFloat = do
    input <- getLine
    case (readMaybe input :: Maybe Float) of Just f -> return f
                                             Nothing -> do getFloat

<强>更新

您可能对这个高度多态的循环版本感兴趣:

{-# LANGUAGE NoMonomorphismRestriction #-}
import Text.Read

getItem = do
  input <- getLine
  case readMaybe input of
    Nothing -> getItem
    Just x  -> return x

我故意写了getItem没有类型签名 - 这是GHC可以推断并填写的内容。我还使用了NoMonomorphismRestriction编译指示,以便getItem保持多态。

这个想法是getItem可以用于任何可以读取的类型 - 浮点数,双打,字符串等。readMaybe使用的类型可以由调用者以各种方式控制。以下是一些例子:

main = do
  f1 <- getItem
  f2 <- getItem
  let r = f1 + f2 :: Float
  print r

通过强制r类型为Float,f1f2也必须为浮点数,因此getItem将尝试解析浮点数。

以下是另一种影响readMaybe使用类型的方法:

main = do
  f <- getItem :: IO Float
  i <- getItem :: IO Int
  print $ f^i  -- compute f raised to the i-th power

答案 1 :(得分:1)

n.nextInt(26) + 'a';

这表明getFloat :: Float getFloat类型的常量,这不是您想要的。

Float

而是指出getFloat :: IO Float 是一个产生getFloat的IO动作。

修复此问题后,您需要在Float前面添加return,正如@ErikR已经解释过的那样。返回将纯浮点值f转换为生成它的IO操作,而不实际执行任何IO。

最后,您不需要上一个f中的dodo getFLoat语法对于排序IO操作很有用:如果只有一个,则它是多余的。