Haskell中有用的ReadLn

Kot*_*kot 2 io haskell functional-programming

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

我想要这样的smth:

?> 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.
Run Code Online (Sandbox Code Playgroud)

ram*_*ion 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
Run Code Online (Sandbox Code Playgroud)

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

? 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)
Run Code Online (Sandbox Code Playgroud)

然而,它并不完美,因为它无法区分不完整的解析和不可能的解析:

? pascalReadLn :: IO (Int, Int, Int, Int)
foo bar
1
2
3
4
... will go forever
Run Code Online (Sandbox Code Playgroud)

自定义实现(沿着相同的行ArgumentTuple)可以通过区分两种故障情况来解决这个问题,例如:

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

 class LineTuple a where
   parseLine :: String -> ParseResult a
Run Code Online (Sandbox Code Playgroud)

  • 我想如果[`Eq`没有16元素元组的实例](http://hackage.haskell.org/package/base-4.7.0.0/docs/Prelude.html#t:Eq),我没有不得不这样做.另外还有`:&`用于任意长度的元组. (2认同)