{"id":38579,"date":"2019-01-10T15:27:58","date_gmt":"2019-01-10T20:27:58","guid":{"rendered":"https:\/\/blog.xamarin.com\/?p=38579"},"modified":"2019-04-01T18:26:07","modified_gmt":"2019-04-02T01:26:07","slug":"hackathon-superweapon-f-and-fabulous","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/xamarin\/hackathon-superweapon-f-and-fabulous\/","title":{"rendered":"Hackathon Superweapon: F# and Fabulous"},"content":{"rendered":"<p>Recently, I participated in <a href=\"https:\/\/twitter.com\/h4ts_hnl\">Hack for the Sea<\/a>, a weekend devoted to applying tech to marine conservation. One of our local challenges was a \u201ccross-platform mobile app for reporting marine debris.\u201d A perfect opportunity to explore the <a href=\"https:\/\/fsprojects.github.io\/Fabulous\/\">Fabulous<\/a>\u00a0 project, which brings the Elmish Model-View-Update (MVU) architecture to Xamarin and F#.<\/p>\n<p><img decoding=\"async\" class=\"aligncenter size-full wp-image-38595\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/Napkin-7-01-10-19-10.31.12-AM.png\" alt=\"\" width=\"749\" height=\"570\" \/><\/p>\n<p>Hackathons are great short and intense challenges that (hopefully) turn a concept into, if not a complete prototype, at least an initial iteration. The camaraderie, short deadline, and free pizza make hackathons an ideal place to explore new technologies.<\/p>\n<p>F# has become a favorite programming language for production work. It has a combination of concise syntax for writing new code and strong types for working with older or unfamiliar code. However, would it be up for the controlled chaos of a hackathon?<\/p>\n<h2>MVU Architecture<\/h2>\n<p>The MVU architecture is an increasingly popular architecture that combines \u201cUI in code,\u201d with a simple-to-use separation between:<\/p>\n<ul>\n<li>A <code>view<\/code> function which describes the user-interface appropriate to the current state of the application.<\/li>\n<li>An <code>update<\/code> function that modifies that state.<\/li>\n<\/ul>\n<p>MVU is not specific to any language, but it fits well with the functional programming mindset. Both <code>view<\/code> and <code>update<\/code> are expected to receive all the information they need from their arguments rather than reading and maintaining instance data.<\/p>\n<p>The MVU architecture and F#\u2019s concise syntax allow one to rapidly create a reporting app that is very similar to a lot of Line of Business (LOB) apps. The app has a combination of data-entry pages and device-generated data (default location and time info, photos, etc.).<\/p>\n<h2>Creating Xamarin.Forms UI in Code<\/h2>\n<p>Creating a Xamarin.Forms UI in code is very straightforward. Define each complex element or page in a local function. A simple one like <code>header<\/code> just contains a static label. A more complex one like <code>locationPage<\/code> can have a message depending on the value (or non-existence) of <code>model.Report.Location<\/code>. As you can see, using the powerful <a href=\"https:\/\/docs.microsoft.com\/en-us\/xamarin\/xamarin-forms\/user-interface\/layouts\/flex-layout\"><code>FlexLayout<\/code><\/a> capability of Xamarin.Forms defines a user interface that lays out properly on any sized device:<\/p>\n<p><code><\/code><\/p>\n<pre class=\"EnlighterJSRAW\">let view model dispatch =\r\n\r\n    let header = \r\n        View.Label(text = \"Report Marine Debris\", fontSize = 24, horizontalTextAlignment = TextAlignment.Center)\r\n\r\n    let locationPage = \r\n        let locMsg = match model.Report |&gt; Option.bind (fun r -&gt; r.Location) with\r\n                     | Some loc -&gt; sprintf \"Location: %.3f, %.3f\" loc.Latitude loc.Longitude\r\n                     | None -&gt; \"Location Unknown\"\r\n\r\n        View.FlexLayout(direction = FlexDirection.Column, alignItems = FlexAlignItems.Center, justifyContent = FlexJustify.SpaceEvenly, \r\n            children = [\r\n                View.Map(requestedRegion = model.MapRegion, minimumWidthRequest = 200.0, widthRequest = 400.0) |&gt; flexGrow 1.0\r\n                View.Label(text = locMsg, verticalTextAlignment = TextAlignment.Center) |&gt; flexGrow 1.0\r\n            ])\r\n\r\n    \/\/ ... more building up of elements and pages ... \r\n\r\n    View.ContentPage(\r\n         content = View.FlexLayout(direction = FlexDirection.Column, alignItems = FlexAlignItems.Center, justifyContent = FlexJustify.SpaceEvenly, \r\n            children = [\r\n                header\r\n                content\r\n                footer\r\n            ]))<\/pre>\n<p>F# reads quite a bit like Python (quite often when writing Python I accidentally type an F#-ism!). One thing possibly surprising to people who&#8217;ve heard of &#8220;strongly typed functional languages&#8221; is the lack of explicit type declarations. While developers <em>may<\/em>\u00a0 add explicit declarations, mostly you rely on the compiler to correctly infer the type and use IntelliSense to give you the precise signature. Other things worth pointing out :<\/p>\n<ul>\n<li>In F# \u201ceverything is an expression.\u201d Both functions and values are declared using <code>let<\/code>;<\/li>\n<li>The <code>|&gt;<\/code> operator is similar to a Unix or PowerShell pipe. It passes the left-hand side value to the right-hand side as an argument;<\/li>\n<li>The <code>match ... with ...<\/code> pattern-matching syntax that generates a compiler error if you miss a case;<\/li>\n<li>The function <code>Option.bind<\/code> which is something like the null-conditional operator.<\/li>\n<\/ul>\n<h2>Using F# to Write a Function<\/h2>\n<p>Once you learn the basics of F#, it\u2019s very readable and concise. Since local functions are trivial to write, you end up refactoring the boilerplate code into local functions. For instance, this \u201cprogress panel\u201d uses different icons to indicate whether or not the user has entered a particular type of data (e.g., \u201cwhat_some.png&#8221; vs \u201cwhat_none.png\u201d). Rather than write a bunch of near-identical <code>if...then...<\/code> blocks, it&#8217;s natural in F# to write a function such as <code>imageFor<\/code> that checks if the data has a particular field (the <code>Some<\/code> case). Then it returns the results of the check and the name of the particular icon to load :\n<code><\/code><\/p>\n<pre class=\"EnlighterJSRAW\">let imageFor f imagePrefix =\r\n    match model.Report |&gt; Option.bind f with\r\n    | Some _ -&gt; (true, sprintf \"%s_some.png\" imagePrefix)\r\n    | None -&gt; (false, sprintf \"%s_none.png\" imagePrefix)\r\n\r\nlet (hasLoc, locImage) = imageFor (fun r -&gt; r.Location) \"where\"\r\nlet (hasDebris, debrisImage) = imageFor (fun r -&gt; r.Material) \"what\"\r\n\/\/ ... etc. for each type of data and icon\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h2>Updating to Update<\/h2>\n<p>To be honest, I love the Model-View-Controller architecture. However, MVU has some clear advantages, particularly in the earliest iterations of a project. Also, it has the potential for &#8220;time-travel debugging&#8221; in which you can &#8220;run the program backward and forwards&#8221; rather than just freezing at a breakpoint.<\/p>\n<p>Key to MVU is the <code>update<\/code> method, which has a signature <code>Msg -&gt; Model -&gt; Model * Cmd&lt;Msg&gt;<\/code> (which would be expressed in C# as <code>Func&lt;Msg,Model,Tuple&lt;Model,Cmd&lt;Msg&gt;&gt;<\/code>). This shows the common functional pattern of \u201cTake a request (<code>Msg<\/code>) and an argument representing the state (<code>Model<\/code>). Act on it, and then return a new version of the state with a new request to tackle the next step in responding to the input.\u201d<\/p>\n<p>For instance, when the GPS gets a reading, the handler creates a <code>LocationFound<\/code> <code>Msg<\/code> with a value of type <code>Xamarin.Essentials.Location<\/code>. In response, the <code>update<\/code> method has this snippet :\n<code><\/code><\/p>\n<pre class=\"EnlighterJSRAW\">| LocationFound loc -&gt;\r\n    let report = { oldReport with Location = Some loc }\r\n    let newRegion = new MapSpan(new Position(loc.Latitude, loc.Longitude), 0.025, 0.025)\r\n    { model with MapRegion = newRegion; Report = Some report }, Cmd.none\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h2>Reports<\/h2>\n<p>A new <code>report<\/code> (the data that is ultimately uploaded to Azure) is created by copying the <code>oldReport<\/code> with the new <code>Location<\/code> value. I then create a new <code>model<\/code> that contains both my new <code>report<\/code> and the <code>MapRegion<\/code> value used in the <code>view<\/code> method as discussed previously.<\/p>\n<p>And that\u2019s it! The handler for <code>LocationFound<\/code> is actually the longest one in the <code>update<\/code> function. If a message requires complex handling, handling it should be done in a separate function. This is particularly nice for async processing, as you can see in the below snippet, that stores the photo to an Azure blob and the data to table storage:\n<code><\/code><\/p>\n<pre class=\"EnlighterJSRAW\">let SubmitReportAsync reportOption =\r\n    async {\r\n        match reportOption with\r\n        | Some report -&gt;\r\n            let photoName = sprintf \"%s.jpg\" ( report.Timestamp.ToString(\"o\") )\r\n            let csa = CloudStorageAccount.Parse connectionString\r\n            let! photoResult = photoSubmissionAsync csa \"image\/jpeg\" report.Photo photoName\r\n            let! submissionResult = reportSubmissionAsync csa report photoResult\r\n            return SubmissionResult submissionResult\r\n        | None -&gt;\r\n            return Error \"Choose data to make report\"\r\n} |&gt; Cmd.ofAsyncMsg\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Unlike the synchronous <code>LocationFound<\/code> handler, this function does some asynchronous work and then fires off a new <code>Cmd<\/code> with a <code>Msg<\/code> that\u2019s either an <code>Error<\/code> message or a <code>SubmissionResult<\/code> message. Rather than a function that tries to do all the business of coordinating async network requests, displaying the results or errors, etc., the MVU architecture facilitates creating clear, discrete single-task functions. In a rapidly-iterating situation such as a hackathon, this is a blast: \u201cOK, what\u2019s next?\u201d \u2026 type a few lines \u2026 run it \u2026 change it \u2026 run it \u2026 \u201cOK, what\u2019s next?\u201d<\/p>\n<h3>Scaling Applications<\/h3>\n<p>There is a trade-off. An <code>update<\/code> function that has to handle lots of <code>Msg<\/code> types whose abstraction levels can vary (for example, <code>SubmitReport<\/code> vs. <code>TakePhoto<\/code>). It\u2019s pretty jarring to be preaching the functional \u201clots of small functions\u201d and have a multi-hundred line <code>update<\/code> function. I recommend watching Zaid Ajaj\u2019s talk \u201c<a href=\"https:\/\/www.youtube.com\/watch?v=-Oc4xJivY78\">Scaling Elmish Applications<\/a>\u201d for a good discussion of the issue.<\/p>\n<h2>Wrapping Up<\/h2>\n<p>In the end, I made my final commit a few minutes before midnight on Saturday, having created from scratch a cross-platform data-entry mobile application, two wrappers for custom controls, and a pile of soda cans to be recycled (Ocean conservation protip: aluminum cans are efficiently recycled compared to plastic bottles, despite their relatively poor packaging-to-content ratio). You can see the interim result (and proof that UX design is not my forte!) at <a href=\"https:\/\/github.com\/lobrien\/MarineDebrisReporting\">my Github repo<\/a>.<\/p>\n<p><img decoding=\"async\" class=\"wp-image-38587 aligncenter\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/Napkin-6-01-10-19-9.17.02-AM.png\" alt=\"\" width=\"251\" height=\"442\" \/><\/p>\n<p>The pressure-cooker environment of a hackathon demands tools that are both high in productivity and fun: exactly how I would describe F# and <a href=\"https:\/\/fsprojects.github.io\/Fabulous\/\">Fabulous<\/a>!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Let me introduce you to F# Functional App Development using Xamarin.Forms with the Fabulous project, which brings the Elmish Model-View-Update (MVU) architecture to Xamarin. It is a great way for F# developers to rapidly build mobile applications as you will see in this blog post.<\/p>\n","protected":false},"author":556,"featured_media":40905,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2,291,367],"tags":[713,16],"class_list":["post-38579","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developers","category-xamarin-platform","category-xamarin-forms","tag-f","tag-xamarin-forms"],"acf":[],"blog_post_summary":"<p>Let me introduce you to F# Functional App Development using Xamarin.Forms with the Fabulous project, which brings the Elmish Model-View-Update (MVU) architecture to Xamarin. It is a great way for F# developers to rapidly build mobile applications as you will see in this blog post.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/38579","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/users\/556"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/comments?post=38579"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/38579\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media\/40905"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media?parent=38579"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/categories?post=38579"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/tags?post=38579"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}