【问题标题】:Reading input from stdin in haskell and converting to list of integers从 Haskell 中的标准输入读取输入并转换为整数列表
【发布时间】:2013-12-24 05:33:53
【问题描述】:

以下代码有什么问题?我只是想在文件中转换以下格式的输入: n - 测试用例数 // n 个数字 n1 n2 (通过标准输入读取)到整数列表中并显示它?

socks :: Int -> Int
socks x = x + 1
strToInt = read :: String -> Int
strLToIntL :: [String] -> [Int]
strLToIntL xs = map (strToInt) xs
main = do
    n <- readLn :: IO Int
    mapM_ putStrLn $ map show $ strLToIntL $ fmap (take n . lines) getContents

运行时出现编译错误:

Couldn't match expected type `Char' with actual type `[Char]'
Expected type: String -> [Char]
  Actual type: String -> [String]
In the second argument of `(.)', namely `lines'
In the first argument of `fmap', namely `(take n . lines)'

【问题讨论】:

  • 为什么不打破那长长的队伍呢?我认为如果您使用多个表达式并为每个分配添加类型签名,您会很快发现问题。找到问题后,您可以将其简化为更紧凑的形式。

标签: haskell


【解决方案1】:

问题是

getContents :: IO String

所以

fmap (take n . lines) getContents :: IO [String]

这不能用于期望 [String] 的东西。要解决此问题,您需要“绑定”IO 操作。使用do 表示法你可以这样写

main = do
  n <- readLine :: IO Int
  input <- fmap (take n . lines) getContents
  mapM_ putStrLn . map show . strLToIntL $ input

你可以把最后一行改成只是

 mapM print . strLToIntL $ input

【讨论】:

    【解决方案2】:

    这里是您的代码已更正,因为您使用的是 monad,因此使用本地绑定而不是使用仿函数更容易解压值。

    socks :: Int -> Int
    socks x = x + 1
    
    strToInt :: String -> Int
    strToInt = read
    
    strLToIntL :: [String] -> [Int]
    strLToIntL xs = map (strToInt) xs
    
    main :: IO ()
    main = do
       n <- readLn
       contents <- getContents
       mapM_ putStrLn $ map show $ strLToIntL $ take n $ lines contents
    

    我认为您要做的是读取整数n,然后从标准输入读取包含整数的n 行。有几种更惯用的方法可以做到这一点,例如:

    import Control.Monad
    
    main :: IO [Integer]
    main = do
      n <- readLn
      forM [1..n] (const readLn)
    

    【讨论】:

    • 感谢您的回答。
    • 当您用const 扔掉数字列表时,为什么不使用replicateMmain = readLn &gt;&gt;= flip replicateM readLn
    【解决方案3】:

    想发布这个相关的例子;它从标准输入读取输入,直到输入 ":q"。

    -- | internally sets the initial state
    -- | to give the illusion that no state is being passed,
    -- | when in fact, the state is set inside the function.
    start = 
        -- | calls the start below, not self
        -- | this is tail recursive; initial state 
        -- | is provided, []
        start []
    
        where 
            -- | this start carries the state along with it
            start initialState = do {
                putStrLn "Enter a number: ";
                raw_input <- getLine;
    
                -- | stop if ":q" entered.
                if (raw_input == ":q") then
                    return ()
                else do { 
                    num <- pure (read raw_input :: Int);
                    newState <- pure (initialState ++ [num]);
                    putStrLn (show newState);
                    start newState;
                }            
            }
    
    main = 
        start
    

    【讨论】:

      猜你喜欢
      • 2013-10-12
      • 2019-07-26
      • 2018-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多