Pergunta

Existe algum equivalente de Frege ao de Haskell? getLine e read analisar a entrada do console na biblioteca padrão?

Atualmente estou fazendo assim:

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

Atualizar:

Frege evoluiu então agora temos getLine na própria biblioteca padrão.Quanto a read, temos métodos de conversão em String.Agora, o problema original é simplesmente,

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

Veja a resposta de Ingo abaixo para mais detalhes.

Foi útil?

Solução

Atualizar:Suporte de E/S em versões mais recentes do Frege

A partir da versão 3.21.80, temos melhor suporte de E/S nas bibliotecas padrão:

  • O tempo de execução fornece stdout e stderr (bufferizado, codificação UTF8 java.io.PrintWriters enrolado java.lang.System.out e java.lang.System.err) e stdin (decodificação UTF8 java.io.BufferedReader enrolado java.lang.System.in)
  • Funções print, println, putStr, putChar escrever para stdout
  • getChar e getLine leia de stdin e lançar exceções no final do arquivo.
  • Os equivalentes de Frege para classes Java como PrintWriter, BufferedWriter etc.são definidos no módulo Java.IO, que é importado automaticamente.Com isso, funcionalidades mais básicas são suportadas.Por exemplo, BufferedReader.readLine tem um tipo de retorno de IO (Maybe String) e sinaliza o fim do arquivo retornando Nothing, como sua contraparte Java, que retorna null em tais casos.

Aqui está um pequeno exemplo de programa que implementa um grep básico:

--- 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

Como Frege ainda é bastante novo, é certo que o suporte da biblioteca ainda é insuficiente, apesar do progresso que já é feito nas áreas mais básicas, como Listas e Mônadas.

Além disso, embora a intenção seja ter um alto grau de compatibilidade com Haskell, especialmente no sistema IO e geralmente nos tópicos relacionados ao sistema de baixo nível, há uma tensão:Deveríamos preferir seguir o caminho Java ou deveríamos realmente tentar emular o caminho de Haskell (que por sua vez é obviamente influenciado pelo que está disponível nas bibliotecas C/POSIX padrão).

De qualquer forma, infelizmente, a área de IO é provavelmente a área mais subdesenvolvida da biblioteca de Frege.Isso também ocorre porque é relativamente fácil escrever rapidamente declarações de funções nativas para um punhado de métodos Java necessários de maneira ad hoc, em vez de perder tempo desenvolvendo uma biblioteca bem elaborada.

Além disso, uma classe Read não existe até agora.Como substituto até que isso seja corrigido, o tipo String possui funções para analisar todos os tipos de números (com base nos métodos Java parseXXX()).

(Nota:Como meus dias também têm apenas 24h e tenho uma família, um cachorro e um trabalho para cuidar, ficaria muito feliz em ter mais colaboradores que ajudem a melhorar o sistema Frege.)

Em relação ao seu código:Sim, acho certo fazer todas as E/S baseadas em caracteres por meio das interfaces do Reader e do Writer.Seu exemplo mostra também que são necessárias funções de conveniência para obter um leitor de entrada padrão.O mesmo vale para o gravador de saída padrão.

Porém, quando você precisasse ler mais de uma linha, eu definitivamente criaria o leitor na função principal e o passaria para as ações de processamento de entrada.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top