【问题标题】:Useful ReadLn in HaskellHaskell 中有用的 ReadLn
【发布时间】:2014-04-25 01:36:22
【问题描述】:

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.

【问题讨论】:

  • 太灵活了。我不相信这种读取功能在 Haskell 中是可能的。
  • 这当然是可能的,虽然不是建议的类型。
  • 不就是简单的readIO还是readIO后跟getLine的序列?
  • 注:在上面,我的真正意思是“不是建议的类型,假设你想为不同大小的元组重用部分或全部实现”。

标签: haskell io functional-programming


【解决方案1】:

您可以使用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

【讨论】:

  • 这将正常工作,直到您尝试输入十六个或更多元素的元组。但我想这太疯狂了:-)
  • 我想如果Eq didn't have an instance for 16 element tuples,我也不必这样做。另外还有:&amp; 用于任意长度的元组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-05
  • 1970-01-01
  • 2010-09-14
相关资源
最近更新 更多