Un compilateur pour générer du code JavaScript à partir de Haskell.
Il a même un site Web et une liste de diffusion.
Vous avez trois options pour obtenir la hâte: l'installation à partir de Hackage, de GitHub ou de l'un des packages binaires prédéfinis. Dans les deux premiers cas, vous devez ajouter Add Cabal's Bin Directory, généralement ~/.cabal/bin , à votre $PATH si vous ne l'avez pas déjà fait. Lors de l'installation à partir du package Mac, Windows ou Generic Linux, vous pouvez ajouter path/to/haste-compiler/bin à votre $PATH . Le package Debian ainsi que l'installateur Windows et le script d'installation en option inclus dans le package Generic Linux s'en occupent automatiquement.
Ou, vous pouvez installer la dernière version stable de Hackage:
$ cabal install haste-compiler
$ haste-boot
La construction de GitHub Source est tout aussi facile. Après avoir vérifié la source, cd à l'arborescence source et exécuté:
$ cabal install
$ haste-boot --force --local
Alternativement, vous pouvez également construire à partir de la source GitHub à l'aide de la pile:
$ stack install
$ haste-boot --force --local
Voir doc/building.md pour plus d'informations sur les exigences et les procédures de construction pour les différentes plates-formes.
Si vous rencontrez des problèmes avec le haste-cabal installé par haste-boot , vous pouvez essayer de le construire à partir de zéro, puis passer le Flag --no-haste-cabal à 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
Lors de l'installation de la hâte de GitHub, vous devriez probablement exécuter la suite de test d'abord, pour vérifier que tout fonctionne. Pour ce faire, exécutez ./runtests.sh dans le répertoire racine Haste. Vous pouvez également exécuter uniquement un test particulier en exécutant ./runtests.sh NameOfTest . La suite de tests utilise l'interpréteur nodejs par défaut, mais cela peut être modifié en définissant la variable d'environnement JS en tant que tel: JS=other-js-interpreter ./runtests.sh . D'autres interprètes JavaScript peuvent ou non fonctionner. runtests.sh n'est pas téléchargé lors de l'installation à partir de Hackage. Vous devrez le télécharger à partir de Github.
Pour construire le compilateur de fermeture patché utilisé lors de la compilation à l'aide de --opt-minify , obtenez la source de fermeture, appliquez patches/closure-argument-removal.patch et construisez-le comme vous le feriez normalement. Ce n'est généralement pas nécessaire cependant, car haste-boot récupère un binaire de fermeture pré-compilé lors de l'exécution.
Pour des instructions de construction plus détaillées, voir doc/building.md .
Haste a été testée pour fonctionner sur les plates-formes Windows et OSX, mais est principalement développée sur GNU / Linux. En tant que tel, fonctionner sur une plate-forme GNU / Linux vous procurera probablement moins de bugs.
Pour compiler votre programme Haskell à un blob JavaScript prêt à être inclus dans un document HTML ou exécuter à l'aide d'un interprète de ligne de commande:
$ hastec myprog.hs
Cela équivaut à appeler GHC - Make MyProg.hs; Main.main sera appelé dès que le blob JS aura terminé le chargement.
Vous pouvez passer les mêmes drapeaux à Hastec que vous passerais normalement à GHC:
$ hastec -O2 -fglasgow-exts myprog.hs
Haste a également son propre ensemble d'arguments de ligne de commande. Invoquez-le avec --help pour en savoir plus à leur sujet. En particulier --opt-all , --opt-minify , --start et --with-js devraient être assez intéressants.
Si vous voulez que votre package se compile avec la hâte et, par exemple, GHC, vous voudrez peut-être utiliser l'extension CPP pour la compilation conditionnelle. Haste définit le symbole du préprocesseur __HASTE__ dans tous les modules qu'il compile. Ce symbole peut également être utilisé pour différencier les versions de hâte, car elle est définie comme une représentation entière de la version hâtive actuelle. Son format est MAJOR*10 000 + MINOR*100 + MICRO . La version 1.2.3 serait donc représentée comme 10203 et 0.4.3 comme 403.
Haste est également livré avec des emballages pour Cabal et GHC-PKG, nommés respectivement Haste-Cabal et Haste-PKG. Vous pouvez les utiliser pour installer des packages comme vous le feriez avec la vanille GHC et Cabal:
$ haste-cabal install mtl
Enfin, vous pouvez interagir avec le code JavaScript à l'aide du module Haste.Foreign dans la bibliothèque haste-lib groupée. Voir doc/js-externals.txt pour plus d'informations à ce sujet. Cette bibliothèque contient également toutes sortes de fonctionnalités pour la manipulation DOM, la gestion des événements, le multitâche préemptif, les graphiques en toile, la manipulation de chaîne JS native, etc.
Pour plus d'informations sur le fonctionnement de la hâte, consultez le rapport Haste, bien que méfiez-vous que des parties de la hâte ont peut-être beaucoup changé.
Vous devriez également consulter la documentation et / ou le code source pour haste-lib , qui réside dans le répertoire libraries/haste-lib , et les petits programmes du répertoire examples , pour commencer.
Lorsque vous rédigez des programmes, vous voudrez probablement utiliser un javascript natif dans votre programme; liaisons aux bibliothèques natives, par exemple. La façon préférée de le faire est le module Haste.Foreign :
{-# LANGUAGE OverloadedStrings #-}
import Haste.Foreign
addTwo :: Int -> Int -> IO Int
addTwo = ffi "(function(x, y) {return x + y;})"
La fonction ffi est un peu plus sûre que le GHC FFI en ce qu'elle applique des invariants de type sur les valeurs renvoyées de JS, et est plus pratique. En termes de performances, il est à peu près aussi rapide que le GHC FFI, sauf pour les types complexes (listes, enregistrements, etc.) où il est un ordre de grandeur plus rapide.
Si vous ne vous sentez pas à l'aise de jeter toute votre base de code JavaScript Legacy, vous pouvez exporter des fonctions sélectionnées à partir de votre programme de hâte et les appeler à partir de 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"));
}
... puis compilez avec:
$ hastec '--start=$HASTE_MAIN(); mymain();' --with-js=legacy.js fun.hs
fun.hs exportera la fonction fun lorsque sa fonction main sera exécutée. Notre JavaScript doit évidemment s'exécuter après cela, nous créons donc notre "vraie" fonction principale dans legacy.js . Enfin, nous disons au compilateur de démarrer le programme en exécutant d'abord la fonction main de Haste (le $HASTE_MAIN est remplacé par le nom que le compilateur choisit pour le main de la hâte), puis de l'exécution de notre propre mymain .
Les mécanismes de Haste.Foreign sont décrits en détail dans cet article.
En utilisant le framework à partir de la hiérarchie du module Haste.App , vous pouvez facilement écrire des applications Web qui communiquent avec un serveur sans avoir à écrire une seule ligne d'Ajax / WebSockets / peu importe. Mieux encore: c'est complètement sûr.
En substance, vous écrivez votre application Web en tant que programme unique - plus de séparation forcée de votre client et de votre code serveur. Vous compilez ensuite votre programme une fois à l'aide de la hâte et une fois que vous utilisez GHC, et les deux compilateurs généreront par magie respectivement le code client et serveur.
Vous devrez que les mêmes bibliothèques soient installées avec la hâte et le GHC vanille (sauf si vous utilisez une compilation conditionnelle pour contourner cela). haste-compiler est livré avec tous les haste-lib , vous n'avez donc besoin de vous en préoccuper que si vous utilisez des bibliothèques tierces. Vous aurez également besoin d'un serveur Web, pour servir vos fichiers HTML et JS; Le binaire généré par le Pass de compilation natif communique uniquement avec la partie client à l'aide de WebSockets et ne sert aucun fichier seul.
Des exemples de Haste.App en action sont disponibles dans examples/haste-app et examples/chatbox .
Pour plus d'informations sur le fonctionnement exactement, consultez ce document.
Vous pouvez construire votre propre ensemble de documents pour Haste-Lib en exécutant cabal haddock dans le répertoire de base Haste comme avec tout autre package.
Ou vous pouvez simplement regarder les documents en ligne.
Haste est capable d'utiliser des bibliothèques Haskell standard. Cependant, certaines opérations primitives ne sont toujours pas implémentées, ce qui signifie que tout code en utilisant vous donnera un avertissement de compilateur, puis meurera au moment de l'exécution avec une erreur de colère. Certaines bibliothèques dépendent également du code C externe - si vous souhaitez utiliser une telle bibliothèque, vous devrez porter les bits C pour vous-même (peut-être en utilisant Emscripten) et les lier à votre programme en utilisant --with-js .
Tous les primops GHC ne sont pas mis en œuvre; Si vous rencontrez un Primop non implémenté, veuillez le signaler avec un petit cas de test qui démontre le problème.
Modèle Haskell est toujours cassé.
Le code généré n'est pas compatible avec ADVANCED_OPTIMIZATIONS du compilateur de fermeture de vanille, car il n'est pas garanti de préserver Function.length . haste-boot regroupe une version correcée de compatibilité de la fermeture qui préserve cette propriété. Invoquer hastec avec l'option --opt-minify utilisera cette version correcée pour miniver le code généré avec des optimisations avancées.