Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MVP: Segunda iteração #5

Open
2 of 4 tasks
yamadapc opened this issue Dec 22, 2015 · 0 comments
Open
2 of 4 tasks

MVP: Segunda iteração #5

yamadapc opened this issue Dec 22, 2015 · 0 comments

Comments

@yamadapc
Copy link
Member

  • Escrever primeiro batch de tutoriais (só vamos entender o que é preciso se implementarmos a ideia)
    • learnyouhaskell
    • learnyouworkhs
  • Mais type-safe
  • Interface melhor
    • O list-prompt precisa conseguir se renderizar propriamente independente do tamanho do terminal
  • i18n
  • Helpers para escrever tutoriais
    • verifica o output
    • roda IO e retorna um boolean
    • roda uma suite de testes do hspec contra uma função do módulo
    • roda uma suite de testes do hspec, tendo a execução/output do módulo fornecido de uma forma simples por outro helper

Tutoriais interativos de fato

Recentemente, brinquei com a ideia de rodar um GHCi como um sub-processo de um programa. Fiz isso para tentar fazer o ghci um pouco melhor. Acho que seria divertido poder lançar uma sessão do GHCi que fosse controlada pelo tutorial que está rodando. Tipo:

$ learnyouhaskell

  Bellow is a live REPL. Try pressing enter.

     ghci> putStrLn "something"<imagine-que-pressiona-enter>
     "something"

  Cool, that's what I wanted. Now what about doing a `map`?
  The type of map is:

     ghci> :t map
     map :: (a -> b) -> [a] -> [b]

  Try it yourself:

     ghci> <cursor-esta-aqui>

Imagine que temos algo como:

uiThread rc wc ewc = do
    _ <- forkIO $ forever $ do
        b <- atomically (readTChan wc)
        ByteString.putStr b
    _ <- forkIO $ forever $ do
        b <- atomically (readTChan ewc)
        ByteString.hPutStr stderr b
    loop
  where
    loop = do
        eof <- hIsEOF stdin
        unless eof $ do
            b <- ByteString.getLine
            atomically (writeTChan rc (b <> "\n"))
            loop

E menos sucetíveis a erros, claro. O que essa função faz é ler texto de dois canais e imprimir ele na tela. E aí podemos ter outra função:

ghciThread :: TChan ByteString -> TChan ByteString -> TChan ByteString -> IO ()
ghciThread rc wc ewc = do
    (inp, out, err, cph) <- ghciStreamingProcess
    readerTid <- forkIO $ chanSource readTChan rc `connect` inp
    outWriterTid <- forkIO $ out `connect` Conduit.ByteString.lines `connect` chanSink writeTChan wc
    errWriterTid <- forkIO $ err `connect` chanSink writeTChan ewc
    e <- waitForStreamingProcess cph
    return ()

Que publica o GHCi nesses canais; dependendo de:

chanSource read c = go
  where
    go = do
        x <- liftIO (atomically (read c))
        Conduit.yield x
        go

chanSink write c = Conduit.List.mapM_ $ liftIO . atomically . write c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant