--- title: "Running R in a Yesod application" date: "2016-09-01" output: html_document --- ```{r setup, include=FALSE} knitr::knit_engines$set(pygmentize = function (options) { f = basename(tempfile("pygmentize", ".", ".txt")) writeLines(options$code, f) on.exit(unlink(f)) code = paste("-f html", options$engine.opts, f) message("running: pygmentize ", code) out = tryCatch(system2("pygmentize", code, stdout = TRUE, stderr = FALSE), error = function(e) { if (!options$error) stop(e) "Error in running pygmentize" }) if (!options$error && !is.null(attr(out, "status"))) stop(paste(out, collapse = "\n")) knitr::engine_output(options, options$code, out) } ) knitr::opts_chunk$set(engine="pygmentize", echo=FALSE, results="asis") ``` ### Basic demo ![](assets/img/RunRInYesod_ss.png) This small app takes two numbers and returns their sum after performing the addition in R. This is an Haskell app created with [Yesod](https://en.wikipedia.org/wiki/Yesod_(web_framework)), and R is called from Haskell with the help of the [inline-R](https://tweag.github.io/HaskellR/) package. You may take a look at my [inline-R demo](http://stla.github.io/stlapblog/posts/CallRinHaskell.html) and at my article [Hello Yesod+Ajax](http://stla.github.io/stlapblog/posts/HelloYesodAjax.html) before. ```{r, engine.opts="-l haskell"} {-# LANGUAGE DataKinds #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE PartialTypeSignatures #-} {-# LANGUAGE OverloadedLists #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE ViewPatterns #-} {-# LANGUAGE OverloadedStrings, DeriveGeneric #-} {-# LANGUAGE TypeFamilies #-} import Yesod import GHC.Generics import qualified Language.R.Instance as R import H.Prelude.Interactive data HelloInlineR = HelloInlineR mkYesod "HelloInlineR" [parseRoutes| / HomeR GET /data DataR PUT |] instance Yesod HelloInlineR data Args = Args { _x :: Double, _y :: Double } deriving (Show,Generic) instance FromJSON Args getHomeR :: Handler () getHomeR = sendFile typeHtml "static/raddition.html" runR :: Double -> Double -> IO(Double) runR x y = do r <- [r|x_hs + y_hs|] return $ (fromSomeSEXP r :: Double) putDataR :: Handler String putDataR = do arguments <- requireJsonBody :: Handler Args r <- liftIO $ runR (_x arguments) (_y arguments) return $ show r main :: IO () main = do R.initialize R.defaultConfig warp 3000 HelloInlineR ``` File *raddition.html*: ```{r, engine.opts="-l html"}

Enter two numbers:



``` Instead of requesting a html file, we can create its contents in the Haskell code: ```{r, engine.opts="-l haskell"} ... import Yesod.Form.Jquery (YesodJquery (urlJqueryJs)) ... instance Yesod HelloInlineR instance YesodJquery HelloInlineR ... getHomeR :: Handler Html getHomeR = defaultLayout $ do setTitle "Yesod + Ajax" getYesod >>= addScriptEither . urlJqueryJs [whamlet|