Ответ 1
Обновление: поддержка ввода/вывода в более поздних версиях Frege
Начиная с версии 3.21.80, мы имеем лучшую поддержку ввода/вывода в стандартных библиотеках:
- Время выполнения предоставляет
stdout
иstderr
(буферизованное кодирование UTF8java.io.PrintWriters
, обернутое вокругjava.lang.System.out
иjava.lang.System.err
) иstdin
(декодирование UTF8java.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 строки, я бы определенно создал читателя в основной функции и передал его на действия обработки ввода.