【问题标题】:How to read in an Int and use it in another function如何读入 Int 并在另一个函数中使用它
【发布时间】:2014-07-05 06:29:53
【问题描述】:

我正在尝试读取 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。即使它应该,正如我所理解的那样
返回(读取 inputjar :: Int) 如何使读取输入在我的函数中可用?

【问题讨论】:

    标签: parsing haskell io


    【解决方案1】:

    您可能不想使用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 -&gt; Int -&gt; Int -&gt; [[Int]] -&gt; [[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 不同。由于main 是一个IO 函数,它不返回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 对应于Applicatives,并且所有Monads 也是Applicatives,所以它并没有真正为我们提供任何东西。在遥远的未来的某个时刻,return 函数可能会完全消失,被pure 完全取代。同样,这些函数都不是 Haskell 语法的一部分,它们在核心库中被定义为普通的普通函数。

    【讨论】:

    • 我想你应该多强调一点 return (Haskell) 与 return (C) 问题,这似乎是用户目前感到困惑的事情。 (是的,它在你的最后一段中,但它目前有点隐藏。只是说^^)
    猜你喜欢
    • 2018-11-15
    • 2015-12-10
    • 1970-01-01
    • 1970-01-01
    • 2016-10-20
    • 2022-11-03
    • 1970-01-01
    • 1970-01-01
    • 2015-11-08
    相关资源
    最近更新 更多