1. Simple regression with Yesod and R

    2016-09-04
    Source

    As announced in a previous article, I did an app with opencpu that performs a simple linear regression in R and returns a report.

    Now I have converted this app to a Yesod+R app. Thus it does not use opencpu anymore. Only Haskell and standard JavaScript libraries.

    The contents of this article are my notes about the way I achieved this goal.

    Structure of the folder

    This folder is available in a Github repo.

    .
    ├── .cabal-sandbox -> /home/stla/.cabal-sandbox/
    ├── cabal.sandbox.config -> /home/stla/cabal.sandbox.config
    ├── FileToBase64.hs
    ├── index.hamlet
    ├── R
    │   ├── child_regression.Rmd
    │   ├── knitRegression.R
    │   └── regression.Rmd
    ├── simplereg.hs
    └── static
        ├── bootstrap
        │   ├── bootstrap-4.0.0.min.css
        │   ├── bootstrap-4.0.0.min.js
        │   └── bootstrap.file-input.js
        ├── css
        │   └── regression.css
        ├── jqplot-1.0.9
        │   ├── jquery.jqplot.min.css
        │   ├── jquery.jqplot.min.js
        │   └── plugins
        │       ├── jqplot.canvasAxisLabelRenderer.js
        │       ├── jqplot.canvasTextRenderer.js
        │       ├── jqplot.cursor.js
        │       ├── jqplot.highlighter.js
        │       └── jqplot.trendline.js
        ├── jquery
        │   └── jquery-1.10.2.min.js
        ├── js
        │   ├── jsontotable.js
        │   └── main.js
        ├── jsonTable
        │   └── jsonTable.js
        └── PapaParse
            └── papaparse-4.1.2.min.js
    • simplereg.hs is the main Haskell code;

    • FileToBase64 is an auxiliary module called by simplereg.hs;

    • index.hamlet is the html code in hamlet format;

    • the static folder contains all js and css files;

    • the R folder contains an R script and auxiliary files.

    The hamlet file, the main css, and the main js

    • Take the file index.html.

    • Remove all the css, put it in the main css file static/css/regression.css (or another css file).

    • Remove all the remote <script> and <link> tags (they will be included by simplereg.hs).

    • Remove the main js script, and put its contents in the file static/js/main.js.

    • Once everything above is done, convert index.html to index.hamlet with html2hamlet.

    The main js script is modified at one place only: the place where it uses the opencpu.js library, obviously. Instead, an Ajax PUT request is used.

    Calling R

    The method, using an Ajax request, is demonstrated on a simple example in Running R in a Yesod application.

    Here we put the main R function knitRegression in the R folder and we source it in Haskell (here):

    runR :: Args -> IO FilePath
    runR (Args dat conflevel filetype) = 
      do
        tmp <- getTemporaryDirectory
        r <- [r|source("R/knitRegression.R")
        knitRegression(jsonlite::fromJSON(dat_hs), conflevel_hs, filetype_hs, tmp_hs)|]
        return $ (fromSomeSEXP r :: FilePath) 
    

    It returns the absolute path of the output file, saved in a temporary folder.

    Base64 encoding

    I have not found a sure way to make the output file available to the client. The solution I adopted consists in encoding the file in base64 with the module I wrote, FileToBase64. Thus the file is encoded to a string which can be used in the href attribute of a <a> tag. It is sent to the client as the result of the Ajax PUT request.