{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Getting started with HaskellR"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Set up HaskellR"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
":ext QuasiQuotes\n",
"import qualified H.Prelude as H\n",
"H.initialize H.defaultConfig"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Doing things in R"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\n",
"Call:\n",
"lm(formula = mpg ~ wt, data = mtcars)\n",
"\n",
"Coefficients:\n",
"(Intercept) wt \n",
" 37.285 -5.344"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"-- print output\n",
"[rprint| lm(mpg ~ wt, data = mtcars) |]"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"-- plot stuff\n",
"-- we just require ggplot2 as we do everything directly in R\n",
"[rgraph| \n",
" require(ggplot2)\n",
" ggplot(diamonds, aes(carat, price)) + geom_point() + theme(aspect.ratio = 1) |]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Assignment also works as usual:\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[1] 3628800"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"[rprint| fact <- function(n) if(n == 0) 1 else n * fact(n - 1) \n",
" fact(10) |]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Call fact again..."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"R Runtime Error: Error in fact(10) : could not find function \"fact\""
],
"text/plain": [
"R Runtime Error: Error in fact(10) : could not find function \"fact\""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"[rprint| fact(10) |]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The embedded R interpreter is stateful, but for global assignment we need to use <<-"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0x00007f86bf8df678"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"[r| fact <<- function(n) if(n == 0) 1 else n * fact(n - 1) |]"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[1] 1.551121e+25"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"[rprint| fact(25) |]"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"## Fine, but my data are in Haskell ... how do I ship them over to R?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The \\_hs suffix is used to splice values from Haskell into the R code:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"-- a Haskell list\n",
"xs = [1..10] :: [Double]\n",
"xs"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[1] 5.5"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"[rprint| mean(xs_hs) |]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can even use functions defined in Haskell in R:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import Data.Int\n",
"fact :: Int32 -> Int32\n",
"fact 0 = 1\n",
"fact n = n * fact (n - 1)\n",
"\n",
"factR x = return $ fact x :: H.R s Int32"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[1] 720"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"n = 6 :: Int32\n",
"[rprint| factR_hs(n_hs) |]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## What if I want to use results from R computations in Haskell?"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[1.1294181047596081,0.1277917949807154,-0.11111631846148341,1.878786090403989]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"get_normals :: Double -> H.R s [Double]\n",
"get_normals n = do\n",
" H.dynSEXP <$> [r| rnorm(n_hs) |]\n",
"result <- H.runRegion $ get_normals 4\n",
"\n",
"result"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now these are just normal Haskell values you can work with:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"result :: [Double]"
],
"text/plain": [
"result :: [Double]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
":t result"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Haskell",
"language": "haskell",
"name": "haskell"
},
"language_info": {
"codemirror_mode": "ihaskell",
"file_extension": ".hs",
"name": "haskell",
"version": "7.10.3"
}
},
"nbformat": 4,
"nbformat_minor": 1
}