Фреге эквивалент Haskell getLine и читать

Есть ли какой-либо эквивалент Frege для Haskell 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

Обновление:

Frege развивается, так что теперь мы имеем getLine в самой стандартной библиотеке. Что касается read, у нас есть методы преобразования в String. Теперь исходная проблема просто,

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

Подробнее см. в Ingo ниже.

Ответы

Ответ 1

Обновление: поддержка ввода/вывода в более поздних версиях Frege

Начиная с версии 3.21.80, мы имеем лучшую поддержку ввода/вывода в стандартных библиотеках:

  • Время выполнения предоставляет 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 и генерировать исключения в конце файла.
  • Эквиваленты Фреге для классов Java, такие как PrintWriter, BufferedWriter и т.д., определены в модуле 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 по-прежнему новенькая, поддержка библиотеки, по-видимому, все еще отсутствует, несмотря на прогресс, который уже выполняется в самых основных областях, таких как списки и Monads.

Кроме того, хотя намерение состоит в том, чтобы иметь высокую степень совместимости с Haskell, особенно в системе ввода-вывода и, как правило, в низкоуровневых системах, связанных с темами, существует напряженность. Должны ли мы скорее пойти на путь Java или должны ли мы на самом деле пытаются эмулировать путь Haskell (что, в свою очередь, явно зависит от того, что доступно в стандартных библиотеках C/POSIX).

В любом случае, IO вещь, вероятно, самая слаборазвитая область библиотеки Фреге, к сожалению. Это также связано с тем, что довольно легко быстро написать декларации собственных функций для нескольких методов Java, которые нужно будет использовать специальным образом, вместо того, чтобы тратить время на разработку хорошо, но из библиотеки.

Кроме того, класс чтения не существует до сих пор. В качестве замены до тех пор, пока это не было исправлено, тип String имеет функции для анализа всех типов номеров (на основе методов Java parseXXX()).

(Боковое замечание: потому что у моих дней также есть только 24 часа, и у меня есть семья, собака и работа, о которой нужно заботиться, я был бы очень рад, если бы у вас было больше участников, которые помогли бы улучшить систему Фреге.)

Что касается вашего кода: Да, я считаю, что правильно использовать все операции ввода-вывода на основе символов через интерфейсы Reader и Writer. В вашем примере также показано, что необходимы удобные функции для получения стандартного считывателя ввода. То же самое справедливо для стандартного записывающего устройства.

Однако, когда вам нужно будет прочитать более 1 строки, я бы определенно создал читателя в основной функции и передал его на действия обработки ввода.