如何设置getLine只接收可以转换为数字的字符串?

时间:2015-10-10 21:42:20

标签: haskell functional-programming

main = do 
putStrLn "Hello,Name please?"
first <- getLine
second <- getLine
third <- getLine
if (second == "divide") then putStrLn (show (read first ::Double )/ (read third :: Double))
    else putStrLn "Cannot do"

所以我想要第一个和第三个变量中的数字,第二个变量将被赋予工作divide,if语句将开始并首先将String转换为Double但是我认为问题是变量First期望像“one”这样的字符串无法转换为Double.How来修复此问题以允许getLine仅接收可以在数字中更改的字符串< / p>

1 个答案:

答案 0 :(得分:2)

这是一个可以帮助你的快速想法:

import Control.Applicative
import Data.Char

getNum :: (Num a, Read a) => IO (Maybe a)
getNum = do
  (x, xs) <- break (not . isDigit ) <$> getLine
  case xs of
    [] -> return $ Just $ read x
    _ -> return Nothing

main :: IO ()
main = do
  x <- getNum :: IO (Maybe Double)
  case x of
    Nothing -> do
      putStrLn "Not a number, try again"
      main
    Just x' ->
      putStrLn $ "Your number: " ++ show x'
  return ()

你不能“使”getLine只接受数字,你可以做一个功能。您甚至可以修改此函数以仅接受非数字前的第一组数字(如果字符串中有任何非数字,则立即返回Nothing。)

<强>更新

这是一个程序,它要求两个数字和一个操作,进行一些值检查:

import Control.Applicative
import Data.Char
import Data.Maybe

getNum :: (Num a, Read a) => IO (Maybe a)
getNum = do
  (x, xs) <- break (not . isDigit ) <$> getLine
  case xs of
    [] -> return $ Just $ read x
    _ -> return Nothing

main :: IO ()
main = do
  putStr "First: "
  x <- getNum :: IO (Maybe Double)

  putStr "Operation: "
  op <- getLine

  putStr "Second: "
  y <- getNum :: IO (Maybe Double)

  if isJust x && isJust y then do
    let
      x' = fromJust x
      y' = fromJust y
    putStr "Result: "
    case op of
      "divide" -> putStrLn $ show $ x' / y'
      "sum" -> putStrLn $ show $ x' + y'
      _ -> putStrLn "No operation"
  else
    putStrLn "Invalid numbers"

  return ()