Page 31 - MSDN Magazine, October 2019
P. 31
Model render View message Update
Figure 2 The Model-View-Update Pattern
capabilities, such as type providers, on top of the rock-solid ASP.NET Core platform, you can create high-performing, reliable, data-centric Web APIs incredibly quickly.
Life in the Browser with Fable
The browser is where it’s at these days, and you’d be hard pushed to find any so-called “full-stack” developer roles that don’t require proficiency in JavaScript, which, despite its many shortcomings, is now the de facto standard for client-side Web programming. Fable is SAFE’s gateway to writing and executing standard F# in the browser without leaving the JavaScript ecosystem.
Why would you want to do this? Because F# lets you take full advantage of its powerful features—from a compiler that can trap types of errors that many other languages can’t, to providing a simple-to-use functional programming model—whilst still letting you take advantage of JavaScript libraries and tools.
There’s even a page on the Fable Web site (fable.io/repl) that lets you experiment and see the JavaScript that gets generated by Fable from F# as you type (see Figure 1)!
Fable is much more than just a simple “transpiler” for F# to Java- Script: It allows you to “hook into” the standard JavaScript ecosystem using well-known tools such as Babel and WebPack to write standard F# that can interact with the JavaScript world. Rather than a closed framework or environment, Fable is more like a gateway into the JavaScript world. Fable doesn’t try to reinvent the wheel—for exam- ple, it doesn’t actually emit JS itself, but uses the well-known Babel tool to do this—meaning that the emitted JavaScript is high-quality and a known quantity. The JS world has a huge ecosystem and set of libraries on top of which, just as Saturn does with the ASP.NET world, you can interact with using idiomatic F#.
Unlike, for example, Web Assembly, which is more of a “sandbox” inside the browser, Fable applications live inside the JavaScript eco- system, so you can naturally use any existing third-party JavaScript library out there from F#. In effect, Fable applications aren’t F# applications running on .NET and the Common Language Runtime (CLR), they’re F# applications running in the browser, using NPM packages and Web tools in the JavaScript ecosystem.
Figure 3 A Simple MVU Application
/// Your data model type Model =
\{ Counter : int \}
/// The different types of messages type Msg =
| Increment
/// Given the current model and a message, give back an updated model let update msg model =
match msg with
| Increment -> \{ Counter = model.Counter + 1 \}
/// Generates the view for the supplied model let view model dispatch =
div \[ Class "main-container" \] \[
span \[ \] \[ str (sprintf "Current value: %i" model.Counter) \]
button \[ OnClick (fun e -> dispatch Increment) \] \[ str "Increment" \]
\]
Fable also comes out-of-the-box with type-safe wrappers around core HTML and Web concepts (such as DOM, Web storage and geolocation), as well as a set of ready-made wrap- pers for common JavaScript libraries. You can also make your own; Fable adds F# extensions that make interop simple, and writing simple F# wrap- pers is quick and easy to do—or you can generate them from TypeScript DefinitelyTyped packages.
msdnmagazine.com
Elmish and the MVU Pattern
Even the JavaScript integration of Fable isn’t enough to write complex Web applications, however. What’s needed is some sort of “pattern” to write applications that developers can follow. Libraries and frameworks such as AngularJS, Vue and React provide such patterns for JavaScript developers. Unfortunately, most of them are heavily influenced by OO patterns, which means FP developers often have to shoehorn their code into a different way of coding.
Thankfully, there’s a better way. The Elm programming language came up with a great FP-friendly paradigm for writing UIs, which has since been adopted in the F# world as the Model-View-Update (or MVU) pattern. There are now .NET “Elmish” libraries for Web, Windows Presentation Foundation, console and (thanks to Microsoft’s excellent Fabulous package) even Xamarin applications. Figure 2 illustrates the MVU pattern at a high level:
Let’s see how this translates into code! Figure 3 shows a simple MVU application that allows you to press a button to increment a counter displayed on the page.
There are a few moving parts here, so let’s take it step-by-step:
You define a “model”: This is a representation of the state of your application; all the data you want to display or work with in the application goes here. In F#, this is best achieved using a record (think of this as a POCO, but as a first-class citizen of the language). In this case, I’m recording the current counter value to display.
Youdefinethe“messages”thatcanoccur:Here,Ijustdefine one—the event that will fire whenever someone clicks the button to increment the counter value. In F#, instead of using class-based
Figure 4 Type Safe IntelliSense for the Browser
October 2019 27