Haskell中有用的ReadLn

时间:2014-04-25 01:36:23

标签: haskell io functional-programming

在Haskell中是否存在像Pascal中的ReadLn这样的内置函数?

我想要像这样的人:

λ> pascalReadLn :: IO (Int, Int, Int, Int)
1 2
3
4
(1,2,3,4)
λ> pascalReadLn :: IO (Int, Int, Int, Int)
1 2 3 4
(1,2,3,4)
λ> pascalReadLn :: IO (Int, Int, Int, Int)
1
2
3
4
(1,2,3,4)
...
etc.

1 个答案:

答案 0 :(得分:7)

你可以使用ReadArgs

来解决这个问题
import ReadArgs

pascalReadLn :: ArgumentTuple a => IO a
pascalReadLn = pascalReadLn' ""
  where pascalReadLn' lines = do
          line <- getLine
          let lines' = lines ++ line
          -- see if we've read enough to successfully parse the desired tuple
          case parseArgsFrom (words lines') of
            Nothing -> pascalReadLn' (lines' ++ "\n")
            Just a  -> return a

它可以根据需要进行有效输入

λ pascalReadLn :: IO (Int, Int, Int, Int)
1 2
3
4
(1,2,3,4)
λ pascalReadLn :: IO (Int, Int, Int, Int)
1 2 3 4
(1,2,3,4)
λ pascalReadLn :: IO (Int, Int, Int, Int)
1
2
3
4
(1,2,3,4)
然而,它并不完美,因为它无法区分不完整的解析和不可能的解析:

λ pascalReadLn :: IO (Int, Int, Int, Int)
foo bar
1
2
3
4
... will go forever

自定义实现(与ArgumentTuple相同)可以通过区分两种失败案例来解决这个问题,例如:

 data ParseResult a = Success a | Incomplete (String -> ParseResult a) | Impossible

 class LineTuple a where
   parseLine :: String -> ParseResult a