Question

Y a-t-il l'équivalent de Frege de Haskell getLine et read Pour analyser les entrées de la console dans la bibliothèque standard?

Actuellement, je le fais comme ceci:

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

Mise à jour:

Frege a évolué alors maintenant nous avons getLine dans la bibliothèque standard elle-même. Pour ce qui est de read, nous avons des méthodes de conversion sur la chaîne. Maintenant, le problème d'origine est simplement,

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

Voir la réponse d'Ingo ci-dessous pour plus de détails.

Était-ce utile?

La solution

MISE À JOUR: Prise en charge des E / S dans les versions plus récentes de Frege

À partir de la version 3.21.80, nous avons une meilleure prise en charge d'E / S dans les bibliothèques standard:

  • Le temps d'exécution fournit stdout et stderr (Encodage tamponné, UTF8 java.io.PrintWriters enroulé autour java.lang.System.out et java.lang.System.err) et stdin (Décodage UTF8 java.io.BufferedReader enroulé autour java.lang.System.in)
  • Les fonctions print, println, putStr, putChar écrire à stdout
  • getChar et getLine Lire de stdin et lancer des exceptions à la fin du fichier.
  • Les équivalents Frege pour les classes Java comme PrintWriter, BufferedWriter etc. sont définis dans le module Java.IO, qui est automatiquement importé. Avec cela, des fonctionnalités plus de base sont prises en charge. Par exemple, BufferedReader.readLine a un type de retour de IO (Maybe String) et signale la fin du fichier en retournant Nothing, comme son homologue Java, qui revient null dans ces cas.

Voici un court exemple de programme qui implémente un Grep de 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

Parce que Frege est encore assez nouveau, le support de la bibliothèque est certes encore manquant, malgré les progrès qui se font déjà dans les domaines les plus élémentaires, comme les listes et les monades.

De plus, alors que l'intention est d'avoir un degré élevé de compatibilité avec Haskell, en particulier dans le système IO et généralement dans les sujets liés au système de bas niveau, il y a une tension: si nous avons plutôt emprunter la voie Java ou si nous essayons vraiment de imitez la voie de Haskell (qui est à son tour évidemment influencé par ce qui est disponible dans les bibliothèques C / POSIX standard).

Quoi qu'il en soit, la chose IO est probablement la zone la plus sous-développée de la bibliothèque Frege, malheureusement. Cela est également dû au fait qu'il est relativement facile d'écrire rapidement les déclarations de fonctions natives pour une poignée de méthodes Java dont on aurait besoin de manière ad hoc, au lieu de prendre le temps de développer une bibliothèque puits.

De plus, une classe de lecture n'existe pas jusqu'à présent. En tant que substitut jusqu'à ce que cela soit corrigé, le type de chaîne a des fonctions pour analyser tous les types de nombres (basés sur les méthodes Java Parsexxx ()).

(Note latérale: Parce que mes journées n'ont également que 24h et j'ai une famille, un chien et un travail à qui nous soucier, je serais très heureux d'avoir plus de contributeurs qui aident à améliorer le système Frege.)

En ce qui concerne votre code: oui, je pense qu'il est juste de faire toutes les E / S basées sur des personnages via les interfaces lecteur et l'écrivain. Votre exemple montre également que les fonctions de commodité pour obtenir un lecteur d'entrée standard sont nécessaires. Il en va de même pour l'écrivain de sortie standard.

Cependant, lorsque vous auriez besoin de lire plus d'une ligne, je créerais définitivement le lecteur dans la fonction principale et le transmettrais aux actions de traitement des entrées.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top