L'equivalente di Frege di Haskell's Getline e leggi
-
13-11-2019 - |
Domanda
C'è l'equivalente di Frege del getLine
Gcode di Haskell e read
Gcode per analizzare l'ingresso dalla console nella biblioteca standard?
Attualmente lo sto facendo così:
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
.
Aggiornamento:
Frege è stato evoluto così ora abbiamo getLine
nella stessa biblioteca standard.Per quanto riguarda read
, abbiamo metodi di conversione sulla stringa.Ora il problema originale è semplicemente,
main _ = do
line <- getLine
println line.atoi
.
Vedi la risposta di Ingo qui sotto per maggiori dettagli.
Soluzione
Aggiornamento: supporto I / O in versioni più recenti di Frege
A partire dalla versione 3.21.80, abbiamo un supporto I / O migliore nelle librerie standard:
- .
- Il runtime fornisce
stdout
estderr
(buffer, utf8java.io.PrintWriters
avvoltojava.lang.System.out
ejava.lang.System.err
) estdin
(UTF8 Decodificajava.io.BufferedReader
avvolto in girojava.lang.System.in
) - Funzioni
print
,println
,putStr
,putChar
Scrivi astdout
-
getChar
egetLine
Leggi dastdin
e lanciare eccezioni sulla fine del file. - Gli equivalenti di Frege per le classi Java come
PrintWriter
,BufferedWriter
ecc. Sono definiti nel moduloJava.IO
, che viene automaticamente importato. Con questo, è supportata più funzionalità di base. Ad esempio,BufferedReader.readLine
ha un tipo di restituzione diIO (Maybe String)
e segnala la fine del file restituendoNothing
, come la controparte Java, che restituiscenull
in tali casi.Ecco un breve programma di esempio che implementa un grep di base:
.--- 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
.Poiché Frege è ancora abbastanza nuovo, il supporto della biblioteca è certamente mancava ancora, nonostante i progressi già fatti nelle aree più basilari, come elenchi e monade.
Inoltre, mentre l'intento è quello di avere un alto grado di compatibilità a Haskell, specialmente nel sistema IO e in generale negli argomenti relativi al sistema di basso livello, vi è una tensione: dovremmo piuttosto andare il modo Java o dovremmo Cerchi davvero di emulare il modo di Haskell (che è a sua volta ovviamente influenzato da ciò che è disponibile nelle librerie standard c / posix).
In ogni caso, la cosa IO è probabilmente l'area più sottosviluppata della Biblioteca di Frege, purtroppo. Questo è anche perché è relativamente facile scrivere rapidamente le dichiarazioni di funzioni native per una manciata di metodi Java, uno avrebbe bisogno in un modo ad hoc, invece di prendersi il tempo per sviluppare una biblioteca benetturiamente fuori.
Inoltre, una classe di lettura non esiste fino ad ora. Come sostitutivo fino a quando non è stato risolto, il tipo di stringa ha funzioni per analizzare tutti i tipi di numeri (in base ai metodi Java Parsexxx ()).
(Nota laterale: perché anche i miei giorni hanno solo 24 ore e ho una famiglia, un cane e un lavoro da prendersi cura, sarei molto felice di avere più contributori che aiutano a rendere il sistema di Frege migliore.) Per quanto riguarda il tuo codice: Sì, sento che è giusto fare tutti i I / O basati su personaggio attraverso le interfacce del lettore e dello scrittore. Il tuo esempio mostra anche che sono necessarie funzioni di convenienza per ottenere un lettore di ingresso standard. Lo stesso vale per lo scrittore di uscita standard.
Tuttavia, quando avresti bisogno di leggere più di 1 riga, creerei sicuramente il lettore nella funzione principale e passeròla alle azioni di elaborazione di ingresso.