如何在Haskell中从IO添加到List。

时间:2018-02-05 21:02:17

标签: list haskell io

我正在尝试编写一个简单的函数,它一次读取一行(我知道它将是整数),然后将它们存储到列表中。然而,对于我的生活,似乎列表是空的。

import System.IO
import Control.Monad

type Int2 = [Int]

valueTab = [] :: [Int]

app [ ] list = list 
app (h:t) list = h:(app t list)

main :: IO ()
main = do
    hSetBuffering stdout NoBuffering -- DO NOT REMOVE

    -- Auto-generated code below aims at helping you parse
    -- the standard input according to the problem statement.

    input_line <- getLine
    let n = read input_line :: Int
    let value = [] :: [Int]

    replicateM n $ do
        input_line <- getLine
        let pi = read input_line :: Int
        hPutStrLn stderr (show input_line)
        hPutStrLn stderr (show valueTab)
        return $ app valueTab [pi]


    -- hPutStrLn stderr "Debug messages..."

    -- Write answer to stdout


    --putStrLn input_line
    return ()

所以当我运行时 8 6 4 3都是靠自己的路线, 它打印6,[],4,[],3 []。

这是我的打印问题,我的列表声明,我存储它们的方式或?我同时使用value和valueTab来检查它是否是范围问题。

注意:代码是编码网站上的样板代码,可在其平台上对其进行测试。假设replicateM只是一个遍历代码x次数的循环。

1 个答案:

答案 0 :(得分:1)

看起来你在codinggame.com上遇到了问题。其他编码站点似乎在他们的Haskell模板上做得更好,特别是对于初学练习 - 模板通常负责所有输入和输出,你只需要提供缺少的纯函数。相比之下,codinggame.com的Haskell模板似乎假设初学者对IO monad有一个非常牢固的掌握,并省略了许多基本细节(例如,replicateM动作的结果实际应该是绑定到您希望填写的变量。

原始模板中的replicateM调用可能类似于:

replicateM n $ do
    input_line <- getLine
    let pi = read input_line :: Int    -- maybe this line was there, maybe not
    return ()

此表达式创建一个复合IO操作,在执行时,将重复以下子操作n次:

  • 读取一行,将读取的字符串绑定到input_line
  • 准备将该行转换为整数值pi(尽管由于未使用pi而永远不会这样做)
  • 无论字符串读取如何,返回“unit”(值())作为子操作的结果

复合操作的值是子动作返回的值的列表。由于这些都是单位,因此复合操作的最终值为列表[(),(),()...()],每行读取一个()。但是,因为此复合动作的值永远不会绑定到变量(即,因为result <- ...表达式之前没有replicateM),所以此列表将被丢弃。

因此,这个模板提供了一种不必要的详细方法来读取n输入行并且不对它们做任何事情。

幸运的是,要使这个模板做一些有用的事情,你需要做的就是让subaction返回一个有用的值(例如,整数pi),这将导致复合动作返回一个列表整数读取,然后确保使用<-表示法将结果列表绑定到变量。

换句话说,你想写:

main = do
    ...

    pis <- replicateM n $ do
        input_line <- getLine
        let pi = read input_line :: Int
        return pi

    hPutStrLn stderr (show pis)

您不需要辅助函数app,也不需要预先声明列表valueTab来包含结果。结果由replicateM自动生成,您只需将其命名即可以使用它。

完整的工作程序如下:

import System.IO
import Control.Monad

type Int2 = [Int]

main :: IO ()
main = do
    hSetBuffering stdout NoBuffering -- DO NOT REMOVE

    -- Auto-generated code below aims at helping you parse
    -- the standard input according to the problem statement.

    input_line <- getLine
    let n = read input_line :: Int
    let value = [] :: [Int]

    pis <- replicateM n $ do
        input_line <- getLine
        let pi = read input_line :: Int
        return pi

    hPutStrLn stderr (show pis)

    -- hPutStrLn stderr "Debug messages..."
    -- Write answer to stdout

    return ()