F# Environment

This notebook builds a reusable environment for F# Jupyter runtimes, based on the Minimal Python 3 environment. Nextjournal's F# environment uses the IfSharp Jupyter kernel, and runs Mono v6.0.0.319 with MSBuild v16.0.0.0, and v10.2.3 of the compiler for F# 4.5. NuGet v5.1.0.6013 and Paket v5.215.0 are available for dependency management.

Learn more about environments on Nextjournal.

You can use this environment by remixing the Nextjournal F# template.

Showcase

Plotting

Two plotting packages are functional under IfSharp: Angara and Xplot.

Angara.Charting

From the IfSharp example notebook.

#I @"/ifsharp"
#load @"Angara.Charting.Paket.fsx"
#load @"Angara.Charting.fsx"

open Angara.Charting
open System

let x = [| for i in 0..99 -> float(i) / 10.0 |]
let y = x |> Array.map (fun x -> sin x)
let z = x |> Array.map (fun x -> cos x)

[ Angara.Charting.Plot.line(x, y); Angara.Charting.Plot.markers(x, z) ] 
|> Angara.Charting.Chart.ofList

XPlot.Plotly

XPlot.Plotly currently requires that a plot's HTML be saved to /results.

open System
open System.IO
#I @"/ifsharp"
#load @"ifsharp/FSharp.Charting.Paket.fsx"
#load @"ifsharp/FSharp.Charting.fsx"
#load @"ifsharp/XPlot.Plotly.Paket.fsx"
#load @"ifsharp/XPlot.Plotly.fsx"
open FSharp.Charting
open XPlot.Plotly

let y0 = [1.; 2.; 3.; 4.; 5.]
let y1 = [6.; 7.; 8.; 9.; 5.]

let trace1 = Box(y = y0)
let trace2 = Box(y = y1)

Chart.Plot [trace1; trace2]
  |> Chart.WithWidth 600
  |> Chart.WithHeight 300

// Kludge to get output
File.WriteAllText("/results/out.html", plot.GetHtml())

Setup

Build F# Environment

Add the official Mono repo.

apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
echo "deb https://download.mono-project.com/repo/ubuntu stable-bionic main" | \
  tee /etc/apt/sources.list.d/mono-official-stable.list

Install dependencies, build tools, Mono, F#, and NuGet.

apt-get -qq update
DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends \
  build-essential gfortran cmake automake libtool libltdl-dev pkg-config \
  mono-devel mono-complete libunwind-dev libssl1.0-dev \
  fsharp nuget
apt-get clean
rm -r /var/lib/apt/lists/* # Clear package list so it isn't stale

Install the charting library.

nuget install FSharp.Charting

Install Paket.

wget https://raw.githubusercontent.com/fsprojects/Paket/master/install.sh
bash install.sh
rm install.sh

Install Jupyter and extensions.

pip install --upgrade jupyter jupyter_console jupyter_client \
  jupyter_contrib_nbextensions jupyter_nbextensions_configurator

Download of IfSharp.

FILENAME="IfSharp.v${IFSHARP_VERSION}.zip"
FILEURL="https://github.com/fsprojects/IfSharp/releases/download/v${IFSHARP_VERSION}/${FILENAME}"

wget --progress=dot:mega -O /results/${FILENAME} ${FILEURL}
IfSharp.v3.0.1.zip

Install IfSharp.

rm -rf ifsharp
mkdir ifsharp
cd ifsharp
unzip 
IfSharp.v3.0.1.zip
mono ifsharp.exe --install

Install extensions.

jupyter contrib nbextension install --user
jupyter nbextensions_configurator enable --user

Check.

du -hsx /
mono -V | grep "Mono JIT compiler version"
msbuild -ver | grep -e "Microsoft.*version"
#dotnet --info | sed -n '1,3p;12,13p;19,22p'
fsharpc --help | grep -e "Microsoft.*version"
nuget | grep "NuGet Version:"
paket --version
jupyter kernelspec list

Test

This should print to stdout, but it uses the display system (i.e. mime bundle) and not jupyter stream channel, I believe this is a design decision on ifsharp side. Except maybe these functions also return the string they print and hence the result.

printfn "Hello World from F#!"
Hello World from F#!
Console.WriteLine("A string: {0}", 42)
A string: 42

This works:

(12/4 + 5 + 7) * 4 - 18
42