Frege 相当于 Haskell 的 getLine 和 read
-
13-11-2019 - |
题
是否存在与哈斯克尔的弗雷格等价的东西 getLine
和 read
在标准库中解析来自控制台的输入?
目前我正在这样做:
import frege.IO
getLine :: IO String
getLine = do
isin <- stdin
isrin <- IO.InputStreamReader.new isin
brin <- IO.BufferedReader.fromISR isrin
line <- brin.readLine
return $ fromExceptionMaybe line
fromExceptionMaybe :: Exception (Maybe a) -> a
fromExceptionMaybe (Right (Just r)) = r
fromExceptionMaybe (Right _) = error "Parse error on input"
fromExceptionMaybe (Left l) = error l.getMessage
pure native parseInt java.lang.Integer.parseInt :: String -> Int
main _ = do
line <- getLine
println $ parseInt line
更新:
弗雷格已经进化了,所以现在我们有 getLine
在标准库本身中。至于 read
, ,我们有 String 的转换方法。现在原来的问题很简单,
main _ = do
line <- getLine
println line.atoi
有关更多详细信息,请参阅下面 Ingo 的回答。
解决方案
更新:Frege 最新版本中的 I/O 支持
从 3.21.80 版本开始,我们在标准库中提供了更好的 I/O 支持:
- 运行时提供
stdout
和stderr
(缓冲,UTF8编码java.io.PrintWriters
包起来java.lang.System.out
和java.lang.System.err
) 和stdin
(UTF8解码java.io.BufferedReader
包起来java.lang.System.in
) - 功能
print
,println
,putStr
,putChar
写给stdout
getChar
和getLine
读自stdin
并在文件末尾抛出异常。- Frege 等价于 Java 类,例如
PrintWriter
,BufferedWriter
ETC。在模块中定义Java.IO
, ,这是自动导入的。这样,就可以支持更多基本功能。例如,BufferedReader.readLine
返回类型为IO (Maybe String)
并通过返回来表示文件结束Nothing
, ,就像它的 Java 对应项一样,返回null
在这种情况下。
这是一个实现基本 grep 的简短示例程序:
--- A simple grep
module examples.Grep where
--- exception thrown when an invalid regular expression is compiled
data PatternSyntax = native java.util.regex.PatternSyntaxException
derive Exceptional PatternSyntax
main [] = stderr.println "Usage: java examples.Grep regex [files ...]"
main (pat:xs) = do
rgx <- return (regforce pat)
case xs of
[] -> grepit rgx stdin
fs -> mapM_ (run rgx) fs
`catch` badpat where
badpat :: PatternSyntax -> IO ()
badpat pse = do
stderr.println "The regex is not valid."
stderr.println pse.getMessage
run regex file = do
rdr <- utf8Reader file
grepit regex rdr
`catch` fnf where
fnf :: FileNotFoundException -> IO ()
fnf _ = stderr.println ("Could not read " ++ file)
grepit :: Regex -> BufferedReader -> IO ()
grepit pat rdr = loop `catch` eof `finally` rdr.close
where
eof :: EOFException -> IO ()
eof _ = return ()
loop = do
line <- rdr.getLine
when (line ~ pat) (println line)
loop
由于 Frege 仍然很新,因此尽管在最基本的领域(例如列表和 Monad)已经取得了进展,但无可否认,库支持仍然缺乏。
此外,虽然目的是与 Haskell 具有高度的兼容性,特别是在 IO 系统和一般低级系统相关主题中,但存在紧张:我们应该选择 Java 方式还是应该真正尝试模仿 Haskell 的方式(这显然又受到标准 C/POSIX 库中可用内容的影响)。
不管怎样,不幸的是,IO 可能是 Frege 库中最不发达的领域。这也是因为以一种特殊的方式快速为少数需要的 Java 方法编写本机函数声明相对容易,而不是花时间开发一个完善的库。
另外,到目前为止,Read 类还不存在。作为此问题修复之前的替代方案,String 类型具有解析所有数字类型的函数(基于 Java parseXXX() 方法)。
(边注:因为我的日子也只有 24 小时,而且我有一个家庭、一只狗和一份工作需要关心,所以我很高兴有更多的贡献者来帮助使弗雷格系统变得更好。)
关于您的代码:是的,我认为通过 Reader 和 Writer 接口执行所有基于字符的 I/O 是正确的。您的示例还表明需要用于获取标准输入读取器的便利功能。这同样适用于标准输出编写器。
但是,当您需要读取超过 1 行时,我肯定会在主函数中创建读取器并将其传递给输入处理操作。