Note: this blog post is part of the F# advent calendar 2019.

# Introduction

In this blog post, we’ll build a website that can solve Reverse Polish Notation (RPN) equations. All code (including the website) will be written in F#, but the equations themselves will be solved using WebAssembly.

# Reverse Polish Notation

In RPN equations, operators (`+`, `-`, etc.) follow their operands (`1`, `3`, etc.). This is known as postfix notation. Its main advantage: parentheses are no longer needed to define precedence. Consider the following equation (in standard mathematical notation):

``````(1 + 3) * (5 - 2)
``````

This is the same equation, but specified in RPN:

``````1 3 + 5 2 - *
``````

To solve this RPN equation we can just interpret its parts as a series of stack operations:

• Push `1` on the stack.
• Push `3` on the stack.
• Pop `3` from the stack. Pop `1` from the stack. Apply the `+` operator to the popped operands. Push `4` on the stack.
• Push `5` on the stack.
• Push `2` on the stack.
• Pop `2` from the stack. Pop `5` from the stack. Apply the `-` operator to the popped operands. Push `3` on the stack.
• Pop `3` from the stack. Pop `4` from the stack. Apply the `*` operator to the popped operands. Push `12` on the stack.

As you can imagine, the code to solve RPN equations will be a lot simpler than code to solve equations in standard mathematical notation, as the latter requires one to handle operator precedence rules and nesting (parentheses).

Side note: the famous Edsger Dijkstra invented the Shunting-yard algorithm to convert from infix notation to postfix notation.

In order for our website to be able to solve RPN equations, we’ll start by building a parser. As said, all our code will be written in F#.

## Parsing

Each RPN equation is composed of:

1. Operands (the integers).
2. Operators (the functions).

We’ll model this as follows:

``````type Operator =
| Sub
| Mul
| Div

type Operand =
| Integer of int

type Expression =
| OperatorExpression of Operator
| OperandExpression of Operand

type Equation =
| Equation of Expression list
``````

Our model allows for both empty- and invalid equations. A more advanced model would make illegal states unrepresentable, but for now we’ll keep it simple.

Not all equations will be valid though. There are three types of errors we’ll cover:

• Empty equations: no operands nor operators.
• Invalid equations: one or more unknown tokens.
• Unbalanced equations: equation does not resolve to a single operand.

We’ll model these errors as follows:

``````type EquationError =
| Empty
| Invalid of string
| Unbalanced
``````

Now on to the actual parsing. First, let’s try to parse an expression (which is either an operand or an operator):

``````let parseExpression (word: string): Result<Expression, EquationError> =
match word with
| "-" -> Ok(OperatorExpression Sub)
| "*" -> Ok(OperatorExpression Mul)
| "/" -> Ok(OperatorExpression Div)
| Int32 i -> Ok(OperandExpression(Integer i))
| _ -> Error(Invalid word)
``````

This is fairly straightforward code, where we map strings to operator expressions and integers to operand expressions using a custom active pattern. Note that the return type is not an `Expression`, but a `Result<Expression, EquationError>`, as we also want to capture if the word we tried to parse was invalid.

Our next step is to convert a `string` to its words (represented as a list of strings):

``````module String =
let words (str: string): string list =
str.Trim().Split([| ' ' |], StringSplitOptions.RemoveEmptyEntries)
|> List.ofArray
``````

Using these two functions, we can start building the `parse` function:

``````let parse (str: string): Result<Equation, EquationError> =
let words = String.words str
let expressions = List.map parseExpression words
...
``````

The `expressions` value has type `Result<Expression, EquationError> list`, so it is a list of `Result`’s. We’d like to convert it to a `Result<Expression list, EquationError>`, as we can then convert the `Expression list` to an `Equation`. We can flatten the `Result list` into a single `Result` using this function:

``````module Result =
let ofList (results: Result<'a, 'b> list): Result<'a list, 'b> =
let folder resultState resultElement =
match resultState, resultElement with
| Ok results, Ok element -> Ok(element :: results)
| Error err, _ -> Error err
| _, Error err -> Error err

results
|> List.fold folder (Ok [])
|> Result.map List.rev
``````

We are now able to create a complete, working version of our `parse` function:

``````let parse (str: string): Result<Equation, EquationError> =
str
|> String.words
|> List.map parseExpression
|> Result.ofList
|> Result.map Equation
``````

Let’s try calling our `parse` function to test it:

``````parse "1 2 +"
val it : Result<Equation,EquationError> =
Ok
(Equation
[OperandExpression (Integer 1); OperandExpression (Integer 2);
``````

Hurray! Parsing works. We’re not completely done with parsing though, as we have two types of errors that we haven’t checked for: empty- and unbalanced equations. To handle these cases, we’ll add the following function:

``````let validate (expressions: Expression list): Result<Expression list, EquationError> =
let rec helper remainder stack =
match remainder, stack with
| [], [] -> Error Empty
| [], [ OperandExpression _ ] -> Ok(expressions)
| OperandExpression i :: xs, _ -> helper xs (OperandExpression i :: stack)
| OperatorExpression i :: xs, OperandExpression _ :: OperandExpression _ :: ys ->
helper xs (OperandExpression(Integer 0) :: ys)
| _ -> Error Unbalanced

helper expressions []
``````

Using pattern matching and recursion, we’re walking through an `Expression list` and check to see if it is empty or unbalanced (an operator is found but not enough operands to work with). We can insert this function into our parsing pipeline using `Result.bind`:

``````let parse str =
str
|> String.words
|> List.map parseExpression
|> Result.ofList
|> Result.bind validate
|> Result.map Equation
``````

Let’s verify that our pipeline detects these errors:

``````parse ""
val it : Result<Equation,EquationError> = Error Empty

parse "3 4 + -"
val it : Result<Equation,EquationError> = Error Unbalanced
``````

Looks like it’s working!

# REPL

Before we move on to the WebAssembly part, let’s build a tiny REPL in which we can solve RPN equations. First, let’s add code to evaluate (solve) an equation:

``````type EvaluationResult =
| EvaluationResult of int

let evaluateExpression (stack: int list) (expression: Expression): int list =
match expression, stack with
| OperandExpression(Integer operand), _ -> operand :: stack
| OperatorExpression Add, x :: y :: xs -> y + x :: xs
| OperatorExpression Sub, x :: y :: xs -> y - x :: xs
| OperatorExpression Mul, x :: y :: xs -> y * x :: xs
| OperatorExpression Div, x :: y :: xs -> y / x :: xs
| _, _ -> failwith "Invalid expression"

let evaluateEquation (Equation expressions): EvaluationResult =
expressions
|> List.fold evaluateExpression []
|> EvaluationResult

let evaluate (str: string): Result<EvaluationResult, EquationError> =
parse str
|> Result.map evaluateEquation
``````

Here you can clearly see the stack-based algorithm reflected that we mentioned in the RPN introduction.

Now all that’s left is to create a REPL loop:

``````let printInstructions(): unit =
printfn "Please enter an equation and evaluate it by pressing enter..."

let eval (input: string): unit =
evaluate input

let printOutcome (EvaluationResult outcome): unit =
printfn "Outcome: %A" outcome

let parserErrorMessage (error: EquationError): string =
match error with
| Empty -> "Empty equation"
| Invalid token -> sprintf "Invalid token: %s" token
| Unbalanced -> "Equation is unbalanced"

let printError (error: EquationError): unit =
let errorMessage = parserErrorMessage error
printfn "Error: %s" errorMessage

let print (result: Result<EvaluationResult, EquationError>): unit =
match result with
| Ok outcome -> printOutcome outcome
| Error error -> printError error

let loop(): unit =
while true do
|> eval
|> print

[<EntryPoint>]
let main _ =
printInstructions()
loop()
0
``````

Simple and elegant. Let’s try out the REPL:

``````Please enter an equation and evaluate it by pressing enter...
1 2 +
Outcome: 3
2 4 * + 7
Error: Equation is unbalanced
``````

Nice. We’re ready to move on solving RPN equations using WebAssembly.

# WebAssembly

Before we dive into the details, let’s refresh our knowledge on what WebAssembly is. The official website has the following definition:

WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.

A great way to learn more about WebAssembly is to check out the cartoon intro to WebAssembly by Lin Clark. For now, just keep in mind that WebAssembly can be executed in the browser and that there is both a binary format (WASM) and a text format (WAT).

As said, our goal will be to have a website that can solve RPN equations. The first step is to parse the equation (using the code we just wrote). The parsed equation will then be compiled to (binary) WebAssembly code. The WebAssembly code is then executed in the browser. Finally, we’ll display the result of the solved equation as well as the WebAssembly used to solve it (binary and text format). Sounds fun? Let’s get to it!

## Generating WebAssembly

In principle, we could be writing F# to output a generic RPN notation solver in WebAssembly, but to keep things simple, we’ll just compile the minimal WebAssembly needed to solve a RPN equation.

The stack-based algorithm used five types of operations:

• Push a number.
• Subtract two numbers.
• Multiply two numbers.
• Divide two numbers.

If we look at the available WebAssembly instructions, we can find direct counterparts for all these operations, which we’ll model as follows:

``````type WebAssemblyInstruction =
| I32Const of int
| I32Sub
| I32Mul
| I32Div
``````

In our domain, we only support a single numeric type: 32-bit integers. In WebAssembly, these types are referred to as value types:

``````type WebAssemblyValueType = I32
``````

For our purposes, a WebAssembly function can be modelled as a name, result type and a list of instructions:

``````type WebAssemblyFunction =
{ Name: string
Result: WebAssemblyValueType
Body: WebAssemblyInstruction list }
``````

Functions in WebAssembly are always organized in a module. Our code will only ever have one function so we can make this a 1-1 mapping:

``````type WebAssemblyModule =
{ Function: WebAssemblyFunction }
``````

We can now convert a parsed equation to its corresponding WebAssembly module:

``````let expressionToWebAssemblyInstruction (expression: Expression): WebAssemblyInstruction =
match expression with
| OperandExpression(Integer i) -> I32Const i
| OperatorExpression Sub -> I32Sub
| OperatorExpression Mul -> I32Mul
| OperatorExpression Div -> I32Div

let equationToWebAssemblyCode (Equation expressions): WebAssemblyInstruction list =
List.map expressionToWebAssemblyInstruction expressions

let equationToWebAssemblyModule (equation: Equation): WebAssemblyModule =
{ Function =
{ Name = "evaluate"
Result = I32
Body = equationToWebAssemblyCode equation } }
``````

In a moment, we’ll write code to convert a `WebAssemblyModule` to WebAssembly text format (WAT) and binary format (WASM). Let’s start with defining some types for the WebAssembly output:

``````type WebAssemblyText = WebAssemblyText of string

type WebAssemblyBinary = WebAssemblyBinary of int list

type WebAssembly =
{ Text: WebAssemblyText
Binary: WebAssemblyBinary }
``````

We can now define the pipeline to compile a RPN equation to WebAssembly:

``````let equationToWebAssembly (equation: Equation): WebAssembly =
let webAssemblyModule = equationToWebAssemblyModule equation

{ Text = Text.outputModule webAssemblyModule
Binary = Binary.outputModule webAssemblyModule }

let convert (str: string): Result<WebAssembly, EquationError> =
parse str
|> Result.map equationToWebAssembly
``````

This code will not compile, as we haven’t yet defined the functions to convert the module to text and binary format. Let’s fix this.

### Text format

While the WebAssembly text format spec is great, Mozilla’s Understanding WebAssembly text format page was invaluable when trying to understand what the text format looks like in practice. In essence, a WebAssembly module is an s-expression, which is a recursive format designed to represent trees.

Here’s the WAT text we’d like to generate for the RPN equation: `1 2 +`:

``````(module
(func (export "evaluate") (result i32)
i32.const 1
i32.const 2
``````

There is not much to the WAT output we want to generate. It defines a module with one function. That function takes no parameters, has three instructions and returns an `i32` value. Finally, the function is exported with the name “evaluate,” which will allow us to call it from JavaScript later.

The actual code to convert our WebAssembly module to its text format representation is fairly straightforward:

``````let outputValueType (valueType: WebAssemblyValueType): string =
match valueType with
| I32 -> "i32"

let outputResult (resultType: WebAssemblyValueType): string =
sprintf "(result %s)" (outputValueType resultType)

let outputInstruction (instruction: WebAssemblyInstruction): string =
match instruction with
| I32Const i -> sprintf "i32.const %i" i
| I32Sub -> "i32.sub"
| I32Mul -> "i32.mul"
| I32Div -> "i32.div_32"

let outputBody (instructions: WebAssemblyInstruction list): string =
instructions
|> List.map outputInstruction
|> String.concat " "

let outputExport (name: string): string =
sprintf "(export \"%s\")" name

let outputFunction (function': WebAssemblyFunction): string =
let export = outputExport function'.Name
let result = outputResult function'.Result
let body = outputBody function'.Body
sprintf "(func %s %s %s)" export result body

let outputModule (module': WebAssemblyModule): WebAssemblyText =
outputFunction module'.Function
|> sprintf "(module %s)"
|> WebAssemblyText
``````

Tiny note: this code doesn’t output the code in an indented format, but it is semantically equivalent.

### Binary format

The binary format is a bit more involved than the text format. Once again, the basis is formed by a module, which is represented as a list of bytes.

The first two parts of a module are fixed, and consist of a magic header and a version:

``````let outputMagicHeader: int list = [ 0x00; 0x61; 0x73; 0x6d ]

let outputVersion: int list = [ 0x01; 0x00; 0x00; 0x00 ]
``````

Note that we defined the values in hexadecimal notation to have them correspond directly to how they are defined in the spec. We could have defined them as bytes, but for the sake of code brevity we’ll use regular ints.

Let’s move on to the contents of a module, which is comprised of zero or more sections. Each section consists of:

• A one-byte section ID.
• The `u32` size of the contents, in bytes.
• The actual contents, which depends on the type of section.

While there are (currently) 12 different types of sections, we only need four of them:

``````type Section =
| Type
| Function
| Export
| Code
``````

The first part of a section, its ID, can be output as follows:

``````let outputSectionIndex (section: Section): int =
match section with
| Type -> 0x01
| Function -> 0x03
| Export -> 0x07
| Code -> 0x0a
``````

The second and third part deal with the section’s contents. The second part is defined as the `u32` size of the contents. If we examine the `u32` spec, we can see that `u32` values must be encoded using the LEB128 encoding. LEB128 encoding is a variable-length encoding, which means that different numbers can be encoded using a different number of bytes.

The LEB128 format has two different algorithms: one for unsigned integers and one for signed integers. Let’s start with the unsigned integers first:

``````let outputUnsignedLEB128 (i: int): int list =

let mutable more = true
let mutable value = i
let mutable bytes = ResizeArray<int>()

while more do
let mutable byte = value &&& bitsOneToSevenMask
value <- value >>> 7
more <- value <> 0

if value <> 0 then byte <- byte ||| bitEightMask

List.ofSeq bytes
``````

Note that we used mutation here. While immutability is great, it is good to remember that not all F# code has to be immutable. Here, we only use mutation inside our function; it is an implementation detail. The actual returned value is a regular, immutable list.

The signed output is similar, but slightly different:

``````let outputSignedLEB128 (i: int): int list =

let mutable more = true
let mutable value = i
let mutable bytes = ResizeArray<int>()

while more do
let mutable byte = value &&& bitsOneToSevenMask
value <- value >>> 7

if value = 0 && (byte &&& bitSevenMask) = 0 then more <- false
elif value = -1 && (byte &&& bitSevenMask) > 0 then more <- false
else byte <- byte ||| bitEightMask

List.ofSeq bytes
``````

Outputting an integer means choosing between the two LEB128 algorithms:

``````let outputInteger (i: int): int list =
if i < 0 then outputSignedLEB128 i
else outputUnsignedLEB128 i
``````

As you might recall, the reason why we needed to output an integer was to output the length of the section’s code. In WebAssembly, bytes prefixed by their length are referred to as a vector:

``````let outputVector (bytes: int list): int list =
let length =
bytes
|> List.length
|> outputInteger
length @ bytes
``````

Outputting a section is then a simple combination of outputting its section index and its vector:

``````let outputSection (section: Section) (bytes: int list): int list =
outputSectionIndex section @ outputVector bytes
``````

Now that we have the basics defined, let’s move on to the output of the individual sections.

#### Type section

The type section encodes the function types of the functions defined in the module (of which we only have one). A function type is defined as the vector of a vector for the parameter types and a vector for the result (return) types:

``````let outputValueType (valueType: WebAssemblyValueType): int =
match valueType with
| I32 -> 0x7f

let outputResult (resultType: WebAssemblyValueType): int =
outputValueType resultType

let outputFunctionTypes (function': WebAssemblyFunction): int list =
let parametersCount = outputInteger 0x00
let resultsCount = outputInteger 0x01
let resultType = outputResult function'.Result
let functionType = 0x60

functionType :: parametersCount @ resultsCount @ [ resultType ]

let outputTypeSection (function': WebAssemblyFunction): int list =
let functionCount = outputUnsignedLEB128 0x01
let functionTypes = outputFunctionTypes function'

functionCount @ functionTypes
|> outputSection Section.Type
``````

#### Function section

The function section links a function’s index to the function type. We have only one function, and thus only one function type, so we can hardcode the number of functions and the function index:

``````let outputFunctionSection: int list =
let functionsCount = outputInteger 0x01
let firstFunctionSignatureIndex = outputInteger 0x00

functionsCount @ firstFunctionSignatureIndex |> outputSection Section.Function
``````

#### Export section

In the export section, everything is listed that should be exposed to the “outside world.” When running WebAssembly in the browser, this means the exported values can be accessed from JavaScript. As we want to call our RPN solving function from JavaScript, we have to export our function.

As we only have one type we want to export (our function), we can use the following code:

``````type ExportType = FunctionExport

let outputExportType (exportType: ExportType): int =
match exportType with
| FunctionExport -> 0x00
``````

Next, we’ll define a function to output a string, which we’ll use in a moment to define the exported function’s name:

``````let outputString (str: string): int list =
str
|> Seq.map int
|> Seq.toList
|> outputVector
``````

Finally, we can glue these things together:

``````let outputExportSection (function': WebAssemblyFunction): int list =
let exportsCount = outputInteger 0x01
let exportName = outputString function'.Name
let exportType = outputExportType FunctionExport
let exportFunctionIndex = outputInteger 0x00

exportsCount @ exportName @ [ exportType ] @ exportFunctionIndex |> outputSection Export
``````

#### Code section

The final section is the code section, which contains (as you might have guessed) the code that a function will execute.

First, we’ll add a mapping from a WebAssembly instruction to its bytes:

``````let outputInstruction (instruction: WebAssemblyInstruction): int list =
match instruction with
| I32Const i -> 0x41: outputInteger i
| I32Add -> [ 0x6a ]
| I32Sub -> [ 0x6b ]
| I32Mul -> [ 0x6c ]
| I32Div -> [ 0x6e ]
``````

Next, the body is defined as number of local declarations (of which we have none), the actual instructions, and finally a special marker for the end of the body:

``````let outputBody (instructions: WebAssemblyInstruction list): int list =
let localDeclarationsCount = outputInteger 0x00
let instructions = List.collect outputInstruction instructions
let bodyEnd = 0x0b

localDeclarationsCount @ instructions @ [ bodyEnd ] |> outputVector
``````

The final code to output the code section is then simple:

``````let outputCodeSection (function': WebAssemblyFunction): int list =
let functionCount = outputInteger 0x01
let body = outputBody function'.Body

functionCount @ body |> outputSection Code
``````

#### Output module

Outputting a module is now a case of appending the outputs of the different sections:

``````let outputModule (module': WebAssemblyModule): WebAssemblyBinary =
let typeSection = outputTypeSection module'.Function
let functionSection = outputFunctionSection
let exportSection = outputExportSection module'.Function
let codeSection = outputCodeSection module'.Function

outputMagicHeader @ outputVersion @ typeSection @ functionSection @ exportSection @ codeSection
|> WebAssemblyBinary
``````

And we’re done! We can now compiling any RPN equation to its WebAssembly format. Let’s start building the website now.

## Building the website

To build the website using only F#, we can use the fabulous (pun intended) Fable compiler. Fable is a compiler that can compile F# code to JavaScript code. Precisely what we need!

Our website will use a particular flavor of Fable called Elmish. With Elmish, one can build applications using the Model-View-Update architecture that was popularized by Elm.

Our first step in building our Elmish application is to define the application’s model. In an Elmish application, the model is used as input to render the website. As such, the model should contain everything that we want to display on our website, which for our application looks like this:

``````type EvaluationResult =
{ Result: int
Wasm: int list
Wat: string }

type EvaluationError =
| WebAssemblyException of exn
| EmptyEquation
| InvalidEquation of string
| UnbalancedEquation

type Model =
{ Evaluation: Result<EvaluationResult, EvaluationError> option
Equation: string }
``````

The types are relative simple. There is an evaluation result that contains the result of the evaluation, as well as the generated WASM (binary format) and WAT (text format). The evaluation result itself is an optional part of the model (there is no evaluation initially). The other part of the model is the equation to solve.

For the first render of the website, Elmish requires us to provide a function that returns the initial model:

``````let init(): Model * Cmd<'a> =
{ Evaluation = None
Equation = "" }, Cmd.none
``````

Of course, we need to be able to update the model if we are to have any interactivity on our website. In the Elmish model, updating the model means sending a message. These messages are defined as a regular discriminated union:

``````type Msg =
| UpdateEquation of string
| EvaluateEquation
| EquationEvaluatedSuccessfully of Evaluation
| EquationEvaluatedWithError of EvaluationError
``````

The next step is to define a function that takes a message and a model, and then returns a model and a command (we’ll get to what a command is):

``````let update (msg: Msg) (model: Model): Model * Cmd<'a> =
match msg with
| UpdateEquation newEquation ->
{ model with Equation = newEquation }, Cmd.none
| EvaluateEquation ->
evaluate model
| EquationEvaluatedSuccessfully evaluation ->
{ model with Evaluation = Some(Ok evaluation) }, Cmd.none
| EquationEvaluatedWithError error ->
{ model with Evaluation = Some(Error error) }, Cmd.none
``````

The `UpdateEquation`, `EquationEvaluatedSuccessfully` and `EquationEvaluatedWithError` paths are relatively straightforward. They take a message with a payload and then update the model with that payload and return the model. These paths also return `Cmd.none` to indicate that there is no new message that needs to be processed.

The interesting path is the one where the user has requested that the equation be evaluated. The `evaluate` function calls the `convert` method, which takes an equation as input and returns the compiled WebAssembly:

``````let evaluate (model: Model): Model * Cmd<'a> =
match convert model.Equation with
| Ok webAssembly -> equationEvaluatedSuccessfully model webAssembly
| Error error -> equationEvaluatedWithError model error
``````

In the error case, we map the `EquationError` to an `EvaluationError` and then return the (unchanged) model and a new message indicating that the model should be updated with the error:

``````let equationEvaluatedWithError (model: Model) (error: EvaluationError): Model * Cmd<'a> =
let evaluationError =
match error with
| Empty -> EmptyEquation
| Invalid token -> InvalidEquation token
| Unbalanced -> UnbalancedEquation

model, Cmd.ofMsg (EquationEvaluatedWithError evaluationError)
``````

This code shows that instead of just updating the model and returning `Cmd.none`, one could also choose to send a new command with a new message, deferring the actual updating of the model to the message handler.

For the success case, where an equation was successfully compiled to WebAssembly, we want to execute the WebAssembly in the browser. This means interacting with browser API’s. Many API’s have type-safe wrappers in Fable, but with the WebAssembly stuff being fairly new, we have to add those wrappers ourselves. Luckily, this is extremely easy:

``````[<AutoOpen>]
module WebAssembly =
type Instance =
{ exports: obj }

type ResultObject =
{ instance: Instance }

[<Emit("WebAssembly.instantiate(\$0)")>]
let instantiate (bufferSource: ArrayBuffer): JS.Promise<ResultObject> = jsNative

[<AutoOpen>]
module Uint8Array =
[<Emit("Uint8Array.from(\$0)")>]
let from (bytes: int list): ArrayBuffer = jsNative
``````

As you can see, we define the browser API’s as regular functions, but with a special `Emit` attribute that Fable will use when converting the F# to JavaScript.

We now have all the infrastructure we need to execute our compiled WebAssembly:

``````let equationEvaluatedSuccessfully model webAssembly =
let (WebAssemblyText(wat)) = webAssembly.Text
let (WebAssemblyBinary(wasm)) = webAssembly.Binary

let onSuccess webAssemblyInBrowser =
EquationEvaluatedSuccessfully
({ Result = webAssemblyInBrowser.instance.exports?evaluate ()
Wasm = wasm
Wat = wat })

let onError ex = EquationEvaluatedWithError(WebAssemblyException ex)

let cmd = Cmd.OfPromise.either WebAssembly.instantiate (Uint8Array.from wasm) onSuccess onError
model, cmd
``````

Running our WebAssembly function is done through the interop code we just wrote: `webAssemblyInBrowser.instance.exports?evaluate()`. The `evaluate()` call is actually our compiled and exported WebAssembly function.

The last part of this function is instructing Fable to execute a function that returns a JavaScript promise (`WebAssembly.instantiate`), and call one of the two passed callbacks when the promise completed successfully or with an error.

The final step in building our website is to write functions to render our UI. With Elmish, rendering HTML is not done in a regular templating language, but using plain F# functions. Consider the following function to output the evaluation output contents:

``````let equationOutputContent (resultClass: string) (text: string): ReactElement =
p []
[ mark
[ Name "result"
Class resultClass ] [ str text ] ]
``````

Calling `equationOutputContent "tertiary" "3"` will render the following HTML:

``````<p><mark name="result" class="tertiary">3</mark></p>
``````

Did you note that the return type of the `equationOutputContent` function was of type `ReactElement`? This gives away the fact that Fable (by default) compiles to React code, in order to actually render the website.

In Elmish, rendering a UI is not much more than just composing functions. We’ll skip over the other functions, but if you’re interested in this bit you can just check out the source code.

And with that we now have a website where we can solve RPN equations using WebAssembly:

# Conclusion

Using F# to parse and solve RPN equations was almost trivial. Modelling the domain using F#’s expressive and low-ceremony type system was an absolute joy. If you are interested in domain modeling using functional techniques, I highly recommend Scott Wlaschin’s Domain Modeling made Functional book.

Generating WebAssembly to solve RPN equations was not very hard. This was helped by the well-written WebAssembly specification. Building the website in F# using Fable was a first for me, but I absolutely loved it. The Elmish part especially was conceptually very appealing, with its simple, functional architecture. Defining HTML output using functions took some time to get used to, but when it did, I really liked it.

The source code of everything described in this blog post can be found at https://github.com/erikschierboom/krakow. You can try out the website at https://krakow-98706.firebaseapp.com/.

4529 Words

2019-12-06 00:00 +0000