Um compilador para gerar código JavaScript a partir de Haskell.
Ele ainda tem um site e uma lista de discussão.
Você tem três opções para obter pressa: instalando a partir de hackage, do GitHub ou de um dos pacotes binários pré-construídos. Nos dois primeiros casos, você precisa adicionar o diretório de bin de Cabal, geralmente ~/.cabal/bin , ao seu $PATH , se você ainda não o fez. Ao instalar no MAC, Windows portátil ou pacote genérico Linux, você pode adicionar path/to/haste-compiler/bin HASTE ao seu $PATH . O pacote Debian, bem como o instalador do Windows e o script de instalação opcional incluído no pacote genérico Linux, cuide disso automaticamente.
Ou você pode instalar a versão estável mais recente da Hackage:
$ cabal install haste-compiler
$ haste-boot
O edifício da fonte do GitHub é igualmente fácil. Depois de verificar a fonte, cd para a árvore de origem e execute:
$ cabal install
$ haste-boot --force --local
Como alternativa, você também pode construir a partir da fonte do GitHub usando a pilha:
$ stack install
$ haste-boot --force --local
Consulte doc/building.md para obter mais informações sobre os requisitos e procedimentos de construção para as várias plataformas.
Se você estiver tendo problemas com a haste-cabal instalada pela haste-boot , pode tentar construí-lo do zero e depois passar a bandeira --no-haste-cabal para haste-boot :
$ git clone https://github.com/valderman/cabal.git
$ cd cabal && git checkout haste-cabal
$ cd Cabal && cabal install
$ cd ../cabal-install && cabal install
Ao instalar a pressa do Github, você provavelmente deve executar a suíte de teste primeiro, para verificar se tudo está funcionando. Para fazer isso, execute ./runtests.sh no diretório raiz da pressa. Você também pode executar apenas um teste específico executando ./runtests.sh NameOfTest . O conjunto de testes usa o intérprete nodejs por padrão, mas isso pode ser modificado definindo a variável de ambiente JS como tal: JS=other-js-interpreter ./runtests.sh . Outros intérpretes de JavaScript podem ou não funcionar. runtests.sh não é baixado ao instalar do Hackage. Você teria que baixá -lo no Github.
Para construir o compilador de fechamento remendado usado ao compilar usando --opt-minify , obtenha a fonte de fechamento, aplique patches/closure-argument-removal.patch e construa-o como normalmente o faria. Isso geralmente não é necessário, no entanto, à medida que haste-boot busca um binário de fechamento pré-compilado quando executado.
Para obter instruções de construção mais detalhadas, consulte doc/building.md .
A pressa foi testada para funcionar em plataformas Windows e OSX, mas é desenvolvida principalmente no GNU/Linux. Como tal, a execução de uma plataforma GNU/Linux provavelmente receberá menos bugs.
Para compilar seu programa Haskell a um JavaScript Blob pronto para ser incluído em um documento HTML ou execução usando um intérprete de linha de comando:
$ hastec myprog.hs
Isso é equivalente a chamar GHC - -make myProg.hs; Main.Main será chamado assim que o JS Blob terminar de carregar.
Você pode passar as mesmas bandeiras para Hastec, que normalmente passaria para o GHC:
$ hastec -O2 -fglasgow-exts myprog.hs
A pressa também tem seu próprio conjunto de argumentos da linha de comando. Invocar com --help para ler mais sobre eles. Em particular --opt-all , --opt-minify , --start start e --with-js deve ser bastante interessante.
Se você deseja que seu pacote compile com pressa e, digamos, GHC, convém usar a extensão do CPP para compilação condicional. Haste define o símbolo do pré -processador __HASTE__ em todos os módulos que ele compila. Esse símbolo também pode ser usado para diferenciar as versões de pressa, pois é definido como uma representação inteira da versão atual. Seu formato é MAJOR*10 000 + MINOR*100 + MICRO . A versão 1.2.3 seria assim representada como 10203 e 0.4.3 como 403.
A pressa também vem com invólucros para Cabal e GHC-PKG, chamado Haste-Cabal e Haste-PKG, respectivamente. Você pode usá -los para instalar pacotes exatamente como faria com o GHC de baunilha e a cabala:
$ haste-cabal install mtl
Por fim, você pode interagir com o código JavaScript usando o módulo Haste.Foreign na biblioteca haste-lib . Consulte doc/js-externals.txt para obter mais informações sobre isso. Esta biblioteca também contém todos os tipos de funcionalidade para manipulação de DOM, manuseio de eventos, multitarefa preventiva, gráficos de tela, manipulação de string nativa JS, etc.
Para obter mais informações sobre como funciona a pressa, consulte o relatório Haste, embora tenha cuidado com que partes da pressa possam ter mudado bastante.
Você também deve dar uma olhada na documentação e/ou código-fonte para haste-lib , que reside no diretório libraries/haste-lib , e os pequenos programas no diretório examples , para começar.
Ao escrever programas, você provavelmente desejará usar algum JavaScript nativo em seu programa; ligações às bibliotecas nativas, por exemplo. A maneira preferida de fazer isso é a Haste.Foreign Módulo Foreign:
{-# LANGUAGE OverloadedStrings #-}
import Haste.Foreign
addTwo :: Int -> Int -> IO Int
addTwo = ffi "(function(x, y) {return x + y;})"
A função ffi é um pouco mais segura do que o FFI do GHC, na medida em que aplica alguns invariantes de tipo nos valores retornados do JS e é mais conveniente. Em termos de desempenho, é aproximadamente tão rápido quanto o FFI do GHC, exceto os tipos complexos (listas, registros etc.) onde é uma ordem de magnitude mais rápida.
Se você não se sentir confortável jogando fora todo o seu legado base de código JavaScript, poderá exportar funções selecionadas do seu programa Haste e chamá -las do JavaScript:
FUN.HS:
{-# LANGUAGE OverloadedStrings #-}
import Haste.Foreign
import Haste.Prim (toJSStr)
fun :: Int -> String -> IO String
fun n s = return $ "The number is " ++ show n ++ " and the string is " ++ s
main = do
export "fun" fun
Legacy.js:
function mymain() {
console.log(Haste.fun(42, "hello"));
}
... então compilar com:
$ hastec '--start=$HASTE_MAIN(); mymain();' --with-js=legacy.js fun.hs
fun.hs exportará a função fun quando sua função main for executada. Nosso JavaScript obviamente precisa ser executado depois disso, por isso criamos nossa função principal "real" em legacy.js . Por fim, dizemos ao compilador para iniciar o programa, executando primeiro a função main de Haste (o $HASTE_MAIN é substituído pelo nome que o compilador escolher para o pressa main ) e depois executar nosso próprio mymain .
A mecânica da Haste.Foreign é descrito em detalhes neste artigo.
Usando a estrutura da hierarquia do módulo Haste.App . O melhor de tudo: é completamente seguro.
Em essência, você escreve seu aplicativo da Web como um único programa - sem mais separação forçada do seu código e código do servidor. Em seguida, você compila seu programa uma vez usando pressa e uma vez usando o GHC, e os dois compiladores gerarão magicamente o código do cliente e do servidor, respectivamente.
Você precisará instalar as mesmas bibliotecas com a pressa e o GHC de baunilha (a menos que você use a compilação condicional para contornar isso). haste-compiler vem com toda a haste-lib , então você só precisa se preocupar com isso se estiver usando bibliotecas de terceiros. Você também precisará de um servidor da Web para atender seus arquivos HTML e JS; O binário gerado pelo passe de compilação nativo se comunica apenas com a parte do cliente usando o WebSockets e não serve nenhum arquivo por conta própria.
Exemplos de pressa. App em ação está disponível em examples/haste-app e examples/chatbox .
Para obter mais informações sobre como exatamente isso funciona, consulte este artigo.
Você pode construir seu próprio conjunto de documentos para libra por pressa executando cabal haddock no diretório da base de pressa, como em qualquer outro pacote.
Ou você pode apenas olhar para os documentos on -line.
A pressa é capaz de usar bibliotecas Haskell padrão. No entanto, algumas operações primitivas ainda não são implementadas, o que significa que qualquer código que use delas oferecerá um aviso de compilador e depois morrerá no tempo de execução com um erro irritado. Algumas bibliotecas também dependem do código C externo -se você deseja usar essa biblioteca, precisará portar os bits C para JavaScript (talvez usando o Emscriptten) e vinculá -los ao seu programa usando --with-js .
Nem todos os PRIMOPs de GHC são implementados; Se você encontrar um PRIMOP não implementado, denuncie -o junto com um pequeno caso de teste que demonstre o problema.
Modelo Haskell ainda está quebrado.
O código gerado não é compatível com o ADVANCED_OPTIMIZATIONS do compilador de fechamento de baunilha, pois não é garantido preservar Function.length . haste-boot agrupa uma versão remendada de compatibilidade do fechamento que preserva essa propriedade. Invocar hastec com a opção --opt-minify usará esta versão corrigida para minimizar o código gerado com otimizações avançadas.