如何在Int中读取并在另一个函数中使用它

时间:2014-05-16 17:39:34

标签: parsing haskell io

我试图在Int中读取然后在纯函数中使用读取值,但它似乎无法正常工作。在搜索了大量资源后,我使用了here

所以我的代码如下:

main = do
putStrLn "Please input a number."
inputjar <- getLine
return (read inputjar :: Int)

哪种方法很好,但是当我想在我的纯函数中使用它时:

usrSetBrick :: [[Int]] -> [[Int]]
usrSetBrick xs = setBrick (main) (main) (main) xs

我收到编译错误:

Couldn't match expected type `Int' with actual type `IO Int'
In the first argument of `setBrick', namely `(main)'
In the expression: setBrick (main) (main) (main) xs
In an equation for `usrSetBrick':
usrSetBrick xs = setBrick (tull) (tull) (tull) xs
Failed, modules loaded: none.

所以根据我的理解,main返回一个int。即便如此,正如我从中可以理解的那样     return(读取inputjar :: Int) 如何在我的函数中使读取输入可用?

1 个答案:

答案 0 :(得分:6)

您可能不希望使用main来返回内容,因为它是您程序的入口点。相反,你可以编写一个函数

getInt :: IO Int
getInt = do
    input <- getLine
    return (read input)  -- Don't have to specify Int here, GHC can figure it out from the type signature

但是,您的函数setBrick(可能是Int -> Int -> Int -> [[Int]] -> [[Int]]类型)无法直接使用getInt。这是设计的,Haskell的类型系统强迫您将IO动作与纯函数分开处理(一旦习惯了它,它就是推理代码的绝佳工具)。相反,你可以做类似

的事情
promptInt :: IO Int
promptInt = do
    putStrLn "Please input a number."
    getInt

usrSetBrick :: [[Int]] -> IO [[Int]]
usrSetBrick xs = do
    a <- promptInt
    b <- promptInt
    c <- promptInt
    return $ setBrick a b c xs

类型IntIO Int在Haskell中不相同,您不能互换使用。这适用于[Int]Maybe IntEither String Int等类型,这些类型与Int无关。由于mainIO函数,因此它不会返回Int,而是返回IO Int。事实上,return根本不是Haskell中的特殊构造,它只是一个正常函数,恰好将值包装在Monad中。在这种情况下,正在使用的MonadIO,因此return (read inputjar :: Int)的类型为IO Int


为了扩展@ Zeta的评论,Haskell的return并不特别,更重要的是不会提前退出。以下代码将演示如下:

doSomething :: IO Int
doSomething = do
    return "Test"  -- Wouldn't type-check if this exited early
    return 123     -- Would type check, but is ignored
    putStrLn "You'll see this line printed"
    return ()      -- Doesn't affect anything
    x <- getLine   -- Still happens
    return 5678
    putStrLn "Your input is meaningless!  Here's a 0"
    return ([1, 2], "hello", "world")
    return 0       -- This is the actual return value

所有这些额外的回报在Haskell中都不起作用(至少在IO monad中)。所有发生的事情都是将值包装在构造函数中并与该函数中的其余语句链接在一起。在Haskell社区中甚至有一些人认为return既不必要又令人困惑。从技术上讲,return相当于pure的{​​{1}},所有Applicative也是Monad s,所以它并没有真正为我们提供任何东西。在遥远的未来的某个时刻,Applicative函数可能会完全消失,完全被return取代。同样,这些函数都不是Haskell语法的一部分,它们在核心库中被定义为普通的普通函数。