15

是否有任何 Frege 等效于 HaskellgetLineread在标准库中解析来自控制台的输入?

目前我正在这样做:

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

更新:

Frege 已经进化,所以现在我们拥有getLine标准库本身。至于read,我们在 String 上有转换方法。现在原来的问题很简单,

main _ = do
  line <- getLine
  println line.atoi

有关更多详细信息,请参阅下面的 Ingo 答案。

4

1 回答 1

12

更新:Frege 最新版本中的 I/O 支持

从 3.21.80 版本开始,我们在标准库中提供了更好的 I/O 支持:

  • 运行时提供stdoutstderr(缓冲,UTF8 编码java.io.PrintWriters环绕java.lang.System.outjava.lang.System.err)和stdin(UTF8 解码java.io.BufferedReader环绕java.lang.System.in
  • 函数print, println, putStr,putChar写入stdout
  • getChar并在文件末尾getLine读取stdin并抛出异常。
  • Java 类的 Frege 等价物PrintWriterBufferedWritermodule 中定义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 还很新,尽管在最基本的领域(如 Lists 和 Monads)已经取得了进展,但承认仍然缺乏对库的支持。

此外,虽然意图是与 Haskell 有高度的兼容性,尤其是在 IO 系统和一般在低级系统相关的主题中,但存在一种张力:我们是宁愿走 Java 路还是真的尝试模仿 Haskell 的方式(这又明显受到标准 C/POSIX 库中可用内容的影响)。

反正 IO 的东西可能是 Frege 库最不发达的领域,可惜了。这也是因为相对容易快速地为少数 Java 方法编写本机函数声明,这是一种特别的方式,而不是花时间开发一个完善的库。

此外,目前还不存在 Read 类。作为解决此问题之前的替代品,String 类型具有解析所有数字类型的函数(基于 Java parseXXX() 方法)。

(旁注:因为我的日子也只有 24 小时,而且我有一个家庭、一条狗和一份工作要关心,所以我很高兴有更多的贡献者来帮助改进 Frege 系统。)

关于您的代码:是的,我认为通过 Reader 和 Writer 接口进行所有基于字符的 I/O 是正确的。您的示例还表明,需要获得标准输入阅读器的便利功能。标准输出编写器也是如此。

但是,当您需要阅读超过 1 行时,我肯定会在主函数中创建阅读器并将其传递给输入处理操作。

于 2012-02-27T15:46:19.507 回答