├── .gitignore ├── LICENSE ├── README.markdown ├── Setup.lhs ├── main └── yesod-slides.hs ├── src └── Slides.hs └── yesod-slides.cabal /.gitignore: -------------------------------------------------------------------------------- 1 | /dist/ 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The following license covers this documentation, and the source code, except 2 | where otherwise indicated. 3 | 4 | Copyright 2011, Hamish Mackenzie. All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY EXPRESS OR 17 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 | EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 22 | OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 23 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 24 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | Quick Tour to Yesod 2 | =================== 3 | 4 | These are the slides I used in my presentation to the Wellington FP Users group. After each slide I showed the code for the slide and discussed how it works. 5 | 6 | The talk covered the parts of Yesod that were of particular interest to me. 7 | 8 | I have now extended the slides to include an example of using GHCJS to run Haskell in the web browser. 9 | 10 | Building GHC with JavaScript output 11 | ----------------------------------- 12 | This version of GHC makes a .js file whenever it outputs an object file. It also "links" the javascript by copying all the files .js files into a .jsexe directory. 13 | It has its own version of cabal so that .js files and .jsexe directories are installed properly. 14 | 15 |
 16 | git clone https://github.com/the-real-blackh/ghc.git
 17 | cd ghc
 18 | ./sync-all -r https://github.com/ghc get
 19 | ./sync-all -r https://github.com/ghc get
 20 | ./sync-all -r https://github.com/ghc get
 21 | ./sync-all -r https://github.com/ghc get
 22 | 
23 | 24 | (You may need to rerun sync-all a few times if like me you get network errors part way through) 25 | 26 |
 27 | rm -rf libraries/Cabal
 28 | git clone https://github.com/the-real-blackh/packages-Cabal.git libraries/Cabal
 29 | cp mk/build.mk.sample mk/build.mk
 30 | perl boot
 31 | ./configure --prefix=/home/hamish/ghcjs
 32 | make
 33 | make install
 34 | 
35 | 36 | To use this compiler add /home/hamish/ghcjs to your path ahead of any other ghc. 37 | 38 |
 39 | export PATH=/home/hamish/ghcjs/bin:$PATH
 40 | 
41 | 42 | You should be able to switch back to your main compiler at any point by simply not including this in you path. 43 | 44 | The global packages (including JavaScript) will be installed to something like 45 | 46 | * ~/ghcjs/lib/ghc-7.1.20110508 47 | 48 | User cabal packages are installed to something like 49 | 50 | * ~/.ghc/i386-darwin-7.1.20110508 51 | * ~/.cabal/lib/*/ghc-7.1.20110508 52 | 53 | Installing cabal-install with GHCJS 54 | ----------------------------------- 55 | You need to make a version of cabal-install that uses the new Cabal package. So that which you run "cabal install" it will copy .js files and .jsexe directories to the install location. 56 | 57 |
 58 | darcs get --lazy http://darcs.haskell.org/cabal-install
 59 | cd cabal-install
 60 | 
61 | 62 | Change build-depends in cabal-install.cabal so it has Cabal >= 1.10.1 && < 1.12 63 | 64 |
 65 | cabal install --ghc-options='-XFlexibleInstances'
 66 | 
67 | 68 | There is a catch. Because your old cabal install installed the dependancies the .js files for these libraries will not have been installed. So you shoule unregister then so they will be installed again with the new cabal-install. 69 | 70 |
 71 | ghc-pkg unregister HTTP
 72 | ghc-pkg unregister network
 73 | ghc-pkg unregister parsec
 74 | ghc-pkg unregister mtl
 75 | ghc-pkg unregister transformers
 76 | ghc-pkg unregister zlib
 77 | 
78 | 79 | Installing GHCJS RTS 80 | -------------------- 81 | The runtime system js files need by GHCJS are in a package. To install this do 82 | 83 |
 84 | git clone https://github.com/hamishmack/ghcjs-rts.git
 85 | cd ghcjs-rts
 86 | cabal install
 87 | 
88 | 89 | Installing Yesod Slides 90 | ----------------------- 91 | Almost there now 92 | 93 |
 94 | git clone https://github.com/hamishmack/yesod-slides.git
 95 | cd yesod-slides
 96 | cabal install --constraint='tagged==0.2' --ghc-options='-XFlexibleInstances'
 97 | yesod-slides
 98 | 
99 | 100 | You need the -XFlixibleInstances because some of the packages on which we depend do not build with this dev version of ghc without it. 101 | 102 | Point your web browser at http://127.0.0.1:3000 103 | 104 | Click to advance from one slide to the next. The GHCJS slde is here the last one http://127.0.0.1:3000/ghcjs 105 | 106 | -------------------------------------------------------------------------------- /Setup.lhs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/runhaskell 2 | > module Main where 3 | > import Distribution.Simple 4 | > main :: IO () 5 | > main = defaultMain 6 | 7 | -------------------------------------------------------------------------------- /main/yesod-slides.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE CPP #-} 2 | #if PRODUCTION 3 | import Slides (withSlides) 4 | import Network.Wai.Handler.Warp (run) 5 | import Paths_yesod_slides 6 | 7 | main :: IO () 8 | main = do 9 | binDir <- getBinDir 10 | withSlides binDir $ run 3000 11 | #else 12 | import Slides (withSlides) 13 | import System.IO (hPutStrLn, stderr) 14 | import Network.Wai.Middleware.Debug (debug) 15 | import Network.Wai.Handler.Warp (run) 16 | import Paths_yesod_slides 17 | 18 | main :: IO () 19 | main = do 20 | let port = 3000 21 | hPutStrLn stderr $ "Application launched, listening on port " ++ show port 22 | binDir <- getBinDir 23 | withSlides binDir $ run port . debug 24 | #endif 25 | -------------------------------------------------------------------------------- /src/Slides.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE TypeFamilies #-} 2 | {-# LANGUAGE QuasiQuotes #-} 3 | {-# LANGUAGE MultiParamTypeClasses #-} 4 | {-# LANGUAGE TemplateHaskell #-} 5 | {-# LANGUAGE OverloadedStrings #-} 6 | {-# LANGUAGE ScopedTypeVariables #-} 7 | module Slides (withSlides, helloString, validatePrime) where 8 | 9 | import Yesod.Core 10 | import Yesod.Helpers.Static 11 | import Network.Wai (Application) 12 | import Text.Hamlet (hamlet, Html) 13 | import Text.Cassius (cassius) 14 | import Text.Julius (julius) 15 | import qualified Text.Blaze.Html5 as H (h1, ul, li) 16 | import Text.Blaze.Renderer.String (renderHtml) 17 | --import Language.Haskell.TH.Quote (QuasiQuoter(..)) 18 | --import Language.Haskell.TH (pprint, runQ) 19 | import System.FilePath (()) 20 | import Control.Monad.Trans.Class (lift) 21 | 22 | data Slides = Slides { 23 | jsexeStatic :: Static 24 | } 25 | 26 | -- This example uses GHC 7 syntax. GHC 6 users should replace 27 | -- [parseRoutes| with [$parseRoutes| 28 | -- [hamlet| with [$hamlet| 29 | -- [cassius| with [$cassius| 30 | -- [julius| with [$julius| 31 | mkYesod "Slides" [parseRoutes| 32 | / RootR GET 33 | /main Main GET 34 | /how How GET 35 | /hamlet Hamlet GET 36 | /hamletvsblaze HamletVsBlaze GET 37 | /cassius Cassius GET 38 | /julius Julius GET 39 | /ghcjs GhcJs GET 40 | /jsexe Jsexe Static jsexeStatic 41 | |] 42 | 43 | instance Yesod Slides where 44 | approot _ = "" 45 | 46 | defaultLayout widget = do 47 | mmsg <- getMessage 48 | pc <- widgetToPageContent $ do 49 | widget 50 | addCassius [cassius| 51 | body 52 | font-family: sans-serif 53 | font-size: 30px 54 | height: 100% 55 | h1 56 | font-size: 40px 57 | h2 58 | font-size: 30px 59 | ul 60 | margin-bottom: 5px 61 | li li 62 | font-size: 25px 63 | input 64 | font-size: 30px 65 | |] 66 | hamletToRepHtml [hamlet| 67 | 68 | 69 |