<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Reed Copsey, Jr.</title>
	<atom:link href="http://reedcopsey.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://reedcopsey.com</link>
	<description>Thoughts on F#, C#, WPF, .NET, and programming for Scientific Visualization</description>
	<lastBuildDate>Thu, 17 Dec 2020 23:08:32 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.6.5</generator>
	<item>
		<title>F# Basics &#8211; Result</title>
		<link>http://reedcopsey.com/2020/12/17/f-basics-result/</link>
					<comments>http://reedcopsey.com/2020/12/17/f-basics-result/#comments</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Thu, 17 Dec 2020 23:00:31 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[F#]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/?p=446</guid>

					<description><![CDATA[This year, for FsAdvent, I&#8217;m taking a request and am going to write about embracing the happy path while writing F#. When coming to F# or other functional programming languages, one of the hurdles I see people face is often rethinking how they approach problems. While many posts talk about how to do this, I [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>This year, for <a href="https://sergeytihon.com/2020/10/22/f-advent-calendar-in-english-2020/">FsAdvent</a>, I&#8217;m taking a request and am going to write about embracing the happy path while writing F#. When coming to F# or other functional programming languages, one of the hurdles I see people face is often rethinking how they approach problems. While many posts talk about <em>how </em>to do this, I want to focus on one of the huge advantages &#8211; less worry and stress about the code working correctly.</p>



<p>For this post, I&#8217;m going to use a small example task &#8211; parsing a file on disk and summarizing some information from it. In this case, we&#8217;ll do something simple &#8211; read a CSV log file of &#8220;events&#8221; that occurred, and get the range of ID numbers from the file. Here is our input file:</p>



<style> #wrap_githubgist137e02d6b103c36646330d9bc85da341 .gist-data {max-height: 100%;} </style><div id="wrap_githubgist137e02d6b103c36646330d9bc85da341" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist106994777\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-events-csv\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-csv  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"events.csv content, created by ReedCopsey on 08:41PM on December 17, 2020.\"\n    >\n\n        <div class=\"blob-interaction-bar\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-search\">\n    <path d=\"M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z\"><\/path>\n<\/svg>\n  <input type=\"text\" name=\"filter\" class=\"form-control js-csv-filter-field blob-filter\" autocapitalize=\"off\"\n         placeholder=\"Search this file…\" aria-label=\"Search this file…\">\n<\/div>\n\n  <div class=\"markdown-body js-check-hidden-unicode\" data-line-alert=\"before\" data-hpc>\n    <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n    <table class=\"js-csv-data csv-data js-file-line-container\">\n      <thead>\n        <tr id=\"file-events-csv-LC1\" class=\"js-file-line\">\n          <td id=\"file-events-csv-L1\" class=\"blob-num js-line-number\" data-line-number=\"1\"><\/td>\n            <th>12/17/2020<\/th>\n            <th>1928<\/th>\n            <th>Child in snow<\/th>\n        <\/tr>\n      <\/thead>\n      <tbody>\n          <tr id=\"file-events-csv-LC2\" class=\"js-file-line\">\n            <td id=\"file-events-csv-L2\" class=\"blob-num js-line-number\" data-line-number=\"2\"><\/td>\n              <td>12/17/2020<\/td>\n              <td>1929<\/td>\n              <td>Child grabbing snow<\/td>\n          <\/tr>\n          <tr id=\"file-events-csv-LC3\" class=\"js-file-line\">\n            <td id=\"file-events-csv-L3\" class=\"blob-num js-line-number\" data-line-number=\"3\"><\/td>\n              <td>12/17/2020<\/td>\n              <td>1930<\/td>\n              <td>Snowball being formed<\/td>\n          <\/tr>\n          <tr id=\"file-events-csv-LC4\" class=\"js-file-line\">\n            <td id=\"file-events-csv-L4\" class=\"blob-num js-line-number\" data-line-number=\"4\"><\/td>\n              <td>12/17/2020<\/td>\n              <td>1931<\/td>\n              <td>Snowball flinging towards tree<\/td>\n          <\/tr>\n          <tr id=\"file-events-csv-LC5\" class=\"js-file-line\">\n            <td id=\"file-events-csv-L5\" class=\"blob-num js-line-number\" data-line-number=\"5\"><\/td>\n              <td>12/17/2020<\/td>\n              <td>1932<\/td>\n              <td>Tree gets hit<\/td>\n          <\/tr>\n          <tr id=\"file-events-csv-LC6\" class=\"js-file-line\">\n            <td id=\"file-events-csv-L6\" class=\"blob-num js-line-number\" data-line-number=\"6\"><\/td>\n              <td>12/17/2020<\/td>\n              <td>1933<\/td>\n              <td>Tree vibrates<\/td>\n          <\/tr>\n          <tr id=\"file-events-csv-LC7\" class=\"js-file-line\">\n            <td id=\"file-events-csv-L7\" class=\"blob-num js-line-number\" data-line-number=\"7\"><\/td>\n              <td>12/17/2020<\/td>\n              <td>1934<\/td>\n              <td>Snow falls off branches<\/td>\n          <\/tr>\n          <tr id=\"file-events-csv-LC8\" class=\"js-file-line\">\n            <td id=\"file-events-csv-L8\" class=\"blob-num js-line-number\" data-line-number=\"8\"><\/td>\n              <td>12/17/2020<\/td>\n              <td>1935<\/td>\n              <td>Snow lands on child and dog<\/td>\n          <\/tr>\n          <tr id=\"file-events-csv-LC9\" class=\"js-file-line\">\n            <td id=\"file-events-csv-L9\" class=\"blob-num js-line-number\" data-line-number=\"9\"><\/td>\n              <td>12/17/2020<\/td>\n              <td>1936<\/td>\n              <td>The dog wimpers, then says &quot;Woof&quot;<\/td>\n          <\/tr>\n          <tr id=\"file-events-csv-LC10\" class=\"js-file-line\">\n            <td id=\"file-events-csv-L10\" class=\"blob-num js-line-number\" data-line-number=\"10\"><\/td>\n              <td>12/17/2020<\/td>\n              <td>1937<\/td>\n              <td>The child hugs dog<\/td>\n          <\/tr>\n          <tr id=\"file-events-csv-LC11\" class=\"js-file-line\">\n            <td id=\"file-events-csv-L11\" class=\"blob-num js-line-number\" data-line-number=\"11\"><\/td>\n              <td>12/17/2020<\/td>\n              <td>1938<\/td>\n              <td>Everybody runs around<\/td>\n          <\/tr>\n          <tr id=\"file-events-csv-LC12\" class=\"js-file-line\">\n            <td id=\"file-events-csv-L12\" class=\"blob-num js-line-number\" data-line-number=\"12\"><\/td>\n              <td>12/17/2020<\/td>\n              <td>1939<\/td>\n              <td>A good time is had by all<\/td>\n          <\/tr>\n      <\/tbody>\n    <\/table>\n  <\/div>\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/137e02d6b103c36646330d9bc85da341/raw/8e6fa76000549a8ead1002e198911c4d9bced85c/events.csv\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/137e02d6b103c36646330d9bc85da341#file-events-csv\" class=\"Link--inTextBlock\">\n          events.csv\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div>



<p>Our task will be to read this file, parse it, and get the range of IDs being used. In this case, we&#8217;ll end up with 2 numbers as our result &#8211; 1928 and 1939.</p>



<p>When working in F#, I often start by describing the data I&#8217;ll be using, as well as the result I want to get or manipulate. Here, each row represents three things; a date, an ID, and a description of the event. We want to eventually get two numbers, a starting ID and an ending ID. In addition, we know there are a few things that could go wrong &#8211; the file might not exist, there might be no data in the file, or the data might be malformed. I&#8217;m going to start by defining a couple of types to help with this:</p>



<style> #wrap_githubgist137e02d6b103c36646330d9bc85da341 .gist-data {max-height: 100%;} </style><div id="wrap_githubgist137e02d6b103c36646330d9bc85da341" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist106994777\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-types-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"types.fs content, created by ReedCopsey on 08:41PM on December 17, 2020.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"types.fs\">\n        <tr>\n          <td id=\"file-types-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-types-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">// The data in our rows<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-types-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-types-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">type Event = { Date : DateTime ; ID : int ; Description : string }<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-types-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-types-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-types-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-types-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">// Our end result<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-types-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-types-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">type Range = { Start : int ; End : int }<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-types-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-types-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-types-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-types-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">// Our potential problems<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-types-fs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-types-fs-LC8\" class=\"blob-code blob-code-inner js-file-line\">type Issue =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-types-fs-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-types-fs-LC9\" class=\"blob-code blob-code-inner js-file-line\">    | IO of message : string * exn : Exception<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-types-fs-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-types-fs-LC10\" class=\"blob-code blob-code-inner js-file-line\">    | DataMissing<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-types-fs-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-types-fs-LC11\" class=\"blob-code blob-code-inner js-file-line\">    | DataMalformed of message : string * exn : Exception<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/137e02d6b103c36646330d9bc85da341/raw/8e6fa76000549a8ead1002e198911c4d9bced85c/types.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/137e02d6b103c36646330d9bc85da341#file-types-fs\" class=\"Link--inTextBlock\">\n          types.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div>



<p>My goal when writing this utility will be to always write in a &#8220;happy path&#8221;. Instead of focusing on handling bad data or errors, I&#8217;m going to try to break everything up into small steps, each a function, that does one thing. I&#8217;m always going to assume my inputs are good, and my output will always either be good result or an Issue from above. Basically, I never want to think about &#8220;bad data&#8221; &#8211; I just want to write code that does something as I go.</p>



<p>In F#, there is a type that helps with this significantly &#8211; <a href="https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/results">Result</a>. The Result type is a discriminated union with two options; an Ok result, or an Error.</p>



<p>We&#8217;ll start by opening our file. In this case, we want a function that takes a filename and returns a Stream we can use for reading. File IO is one place where exception handling is nearly required, so I&#8217;m using that to create my error case:</p>



<style> #wrap_githubgist137e02d6b103c36646330d9bc85da341 .gist-data {max-height: 100%;} </style><div id="wrap_githubgist137e02d6b103c36646330d9bc85da341" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist106994777\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-open_file-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"open_file.fs content, created by ReedCopsey on 08:41PM on December 17, 2020.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"open_file.fs\">\n        <tr>\n          <td id=\"file-open_file-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-open_file-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">let openFile filename =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-open_file-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-open_file-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">    try<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-open_file-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-open_file-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">        File.OpenRead filename<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-open_file-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-open_file-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">        |&gt; Result.Ok<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-open_file-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-open_file-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">    with<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-open_file-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-open_file-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">    | e -&gt; <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-open_file-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-open_file-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">        IO(message = &quot;Could not open file&quot;, exn = e)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-open_file-fs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-open_file-fs-LC8\" class=\"blob-code blob-code-inner js-file-line\">        |&gt; Result.Error<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/137e02d6b103c36646330d9bc85da341/raw/8e6fa76000549a8ead1002e198911c4d9bced85c/open_file.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/137e02d6b103c36646330d9bc85da341#file-open_file-fs\" class=\"Link--inTextBlock\">\n          open_file.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div>



<p>This function will follow a common pattern &#8211; it takes an input (filename) and creates a Result: <code>val openFile : filename:string -&gt; Result</code></p>



<p>To parse the file, I&#8217;m going to use the <a href="https://joshclose.github.io/CsvHelper/examples/reading/reading-by-hand">CsvHelper</a> library. This will allow me to not think about parsing the &#8220;hard parts&#8221; of CSV, like strings with embedded commas or quotes. Now we need a small function to take a stream from our openFile and convert it to a CsvReader:</p>



<style> #wrap_githubgist137e02d6b103c36646330d9bc85da341 .gist-data {max-height: 100%;} </style><div id="wrap_githubgist137e02d6b103c36646330d9bc85da341" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist106994777\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-open_csv-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"open_csv.fs content, created by ReedCopsey on 08:41PM on December 17, 2020.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"open_csv.fs\">\n        <tr>\n          <td id=\"file-open_csv-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-open_csv-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">let openCsv (strm : Stream) =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-open_csv-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-open_csv-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">    new CsvReader(new StreamReader(strm), Globalization.CultureInfo.InvariantCulture)<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/137e02d6b103c36646330d9bc85da341/raw/8e6fa76000549a8ead1002e198911c4d9bced85c/open_csv.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/137e02d6b103c36646330d9bc85da341#file-open_csv-fs\" class=\"Link--inTextBlock\">\n          open_csv.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div>



<p>Here, we know, if we have a valid stream, we&#8217;ll get a valid reader, so we can just write a simple <code>Stream -&gt; CsvReader</code> helper. We can put these together with Result.map, which allows us to take an &#8220;Ok&#8221; result and use it&#8217;s value to make a new result.</p>



<style> #wrap_githubgist137e02d6b103c36646330d9bc85da341 .gist-data {max-height: 100%;} </style><div id="wrap_githubgist137e02d6b103c36646330d9bc85da341" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist106994777\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-make_csv-fsx\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"make_csv.fsx content, created by ReedCopsey on 08:41PM on December 17, 2020.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"make_csv.fsx\">\n        <tr>\n          <td id=\"file-make_csv-fsx-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-make_csv-fsx-LC1\" class=\"blob-code blob-code-inner js-file-line\">let file = openFile &quot;C:\\\\users\\\\reedc\\\\desktop\\\\events.csv&quot;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-make_csv-fsx-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-make_csv-fsx-LC2\" class=\"blob-code blob-code-inner js-file-line\">let csv = file |&gt; Result.map openCsv<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/137e02d6b103c36646330d9bc85da341/raw/8e6fa76000549a8ead1002e198911c4d9bced85c/make_csv.fsx\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/137e02d6b103c36646330d9bc85da341#file-make_csv-fsx\" class=\"Link--inTextBlock\">\n          make_csv.fsx\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div>



<p>Running in FSI, with a good filename, gives us <code>val csv : Result = Ok CsvHelper.CsvReader</code>. With a bad filename, you get: </p>



<p><code>val csv : Result =<br>Error<br>(IO<br>("Could not open file",<br>System.IO.FileNotFoundException: Could not find file</code>&#8230;</p>



<p>Now that our file is opened, we can move onto parsing. Again, we&#8217;ll assume we have a good input (our reader), and just write routines to just parse. In this case, I&#8217;m going to write a function to parse a single row and create an option, and a separate function to parse until we receive None, which will return our Result. </p>



<p>This does get a little uglier with the routine to read all of the rows. We want to make sure to close our file (we effectively pass ownership), so we need the try/finally to dispose of it anytime our routine to open succeeded. We&#8217;ll use a simple try/with to handle parsing errors. Using Seq.initInfinite and Seq.takeWhile allows us to &#8220;loop&#8221; through our data until we return None:</p>



<style> #wrap_githubgist137e02d6b103c36646330d9bc85da341 .gist-data {max-height: 100%;} </style><div id="wrap_githubgist137e02d6b103c36646330d9bc85da341" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist106994777\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-read_rows-fsx\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"read_rows.fsx content, created by ReedCopsey on 08:41PM on December 17, 2020.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"read_rows.fsx\">\n        <tr>\n          <td id=\"file-read_rows-fsx-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-read_rows-fsx-LC1\" class=\"blob-code blob-code-inner js-file-line\">let readRow (reader : CsvReader) =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-read_rows-fsx-LC2\" class=\"blob-code blob-code-inner js-file-line\">    if reader.Read () then<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-read_rows-fsx-LC3\" class=\"blob-code blob-code-inner js-file-line\">            let evt = { <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-read_rows-fsx-LC4\" class=\"blob-code blob-code-inner js-file-line\">                        Date = reader.GetField&lt;DateTime&gt;(0) ;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-read_rows-fsx-LC5\" class=\"blob-code blob-code-inner js-file-line\">                        ID = reader.GetField&lt;int&gt;(1) ;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-read_rows-fsx-LC6\" class=\"blob-code blob-code-inner js-file-line\">                        Description = reader.GetField&lt;string&gt;(2)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-read_rows-fsx-LC7\" class=\"blob-code blob-code-inner js-file-line\">                      }<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-read_rows-fsx-LC8\" class=\"blob-code blob-code-inner js-file-line\">            Some evt<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-read_rows-fsx-LC9\" class=\"blob-code blob-code-inner js-file-line\">    else None<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-read_rows-fsx-LC10\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-read_rows-fsx-LC11\" class=\"blob-code blob-code-inner js-file-line\">let readRowsAndClose reader =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L12\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"12\"><\/td>\n          <td id=\"file-read_rows-fsx-LC12\" class=\"blob-code blob-code-inner js-file-line\">    try<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L13\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"13\"><\/td>\n          <td id=\"file-read_rows-fsx-LC13\" class=\"blob-code blob-code-inner js-file-line\">        try<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L14\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"14\"><\/td>\n          <td id=\"file-read_rows-fsx-LC14\" class=\"blob-code blob-code-inner js-file-line\">            let rows = <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L15\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"15\"><\/td>\n          <td id=\"file-read_rows-fsx-LC15\" class=\"blob-code blob-code-inner js-file-line\">                Seq.initInfinite (fun _ -&gt; readRow reader)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L16\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"16\"><\/td>\n          <td id=\"file-read_rows-fsx-LC16\" class=\"blob-code blob-code-inner js-file-line\">                |&gt; Seq.takeWhile (fun r -&gt; r.IsSome)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L17\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"17\"><\/td>\n          <td id=\"file-read_rows-fsx-LC17\" class=\"blob-code blob-code-inner js-file-line\">                |&gt; Seq.choose id<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L18\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"18\"><\/td>\n          <td id=\"file-read_rows-fsx-LC18\" class=\"blob-code blob-code-inner js-file-line\">                |&gt; Seq.toList<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L19\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"19\"><\/td>\n          <td id=\"file-read_rows-fsx-LC19\" class=\"blob-code blob-code-inner js-file-line\">            if List.isEmpty rows then<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L20\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"20\"><\/td>\n          <td id=\"file-read_rows-fsx-LC20\" class=\"blob-code blob-code-inner js-file-line\">                Result.Error DataMissing<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L21\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"21\"><\/td>\n          <td id=\"file-read_rows-fsx-LC21\" class=\"blob-code blob-code-inner js-file-line\">            else Result.Ok rows<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L22\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"22\"><\/td>\n          <td id=\"file-read_rows-fsx-LC22\" class=\"blob-code blob-code-inner js-file-line\">        with<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L23\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"23\"><\/td>\n          <td id=\"file-read_rows-fsx-LC23\" class=\"blob-code blob-code-inner js-file-line\">        | e -&gt; <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L24\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"24\"><\/td>\n          <td id=\"file-read_rows-fsx-LC24\" class=\"blob-code blob-code-inner js-file-line\">            DataMalformed (&quot;Unable to parse data&quot;, e)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L25\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"25\"><\/td>\n          <td id=\"file-read_rows-fsx-LC25\" class=\"blob-code blob-code-inner js-file-line\">            |&gt; Result.Error<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L26\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"26\"><\/td>\n          <td id=\"file-read_rows-fsx-LC26\" class=\"blob-code blob-code-inner js-file-line\">    finally<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-read_rows-fsx-L27\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"27\"><\/td>\n          <td id=\"file-read_rows-fsx-LC27\" class=\"blob-code blob-code-inner js-file-line\">        reader.Dispose ()<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/137e02d6b103c36646330d9bc85da341/raw/8e6fa76000549a8ead1002e198911c4d9bced85c/read_rows.fsx\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/137e02d6b103c36646330d9bc85da341#file-read_rows-fsx\" class=\"Link--inTextBlock\">\n          read_rows.fsx\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div>



<p>Our final step is to reduce the Event list to our two numbers:</p>



<style> #wrap_githubgist137e02d6b103c36646330d9bc85da341 .gist-data {max-height: 100%;} </style><div id="wrap_githubgist137e02d6b103c36646330d9bc85da341" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist106994777\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-get_ids-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"get_ids.fs content, created by ReedCopsey on 08:41PM on December 17, 2020.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"get_ids.fs\">\n        <tr>\n          <td id=\"file-get_ids-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-get_ids-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">let getIds (events : Event list) =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-get_ids-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-get_ids-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">    let ids = events |&gt; List.map (fun e -&gt; e.ID)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-get_ids-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-get_ids-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">    let min = ids |&gt; List.min<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-get_ids-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-get_ids-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">    let max = ids |&gt; List.max<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-get_ids-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-get_ids-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">    { Start = min ; End = max }<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/137e02d6b103c36646330d9bc85da341/raw/8e6fa76000549a8ead1002e198911c4d9bced85c/get_ids.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/137e02d6b103c36646330d9bc85da341#file-get_ids-fs\" class=\"Link--inTextBlock\">\n          get_ids.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div>



<p>Now that we have all of the pieces, we can stream these together. We will use two functions from the Result module in the core libraries to string these together &#8211; Result.map and Result.bind.</p>



<p>Whenever we have a function that doesn&#8217;t produce an error case, we will use map. When we have a function that takes our input and might need an error case, we will use bind. In our case, openFile and getIds both &#8220;always work&#8221; if their input are good, so we can map them. readRowsAndClose can map the data through to a list, but can also create an error case, so we will use bind. When stringing these together, we end up with:</p>



<style> #wrap_githubgist137e02d6b103c36646330d9bc85da341 .gist-data {max-height: 100%;} </style><div id="wrap_githubgist137e02d6b103c36646330d9bc85da341" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist106994777\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-result-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"result.fs content, created by ReedCopsey on 08:41PM on December 17, 2020.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"result.fs\">\n        <tr>\n          <td id=\"file-result-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-result-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">let result = <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-result-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-result-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">    openFile &quot;C:\\\\users\\\\reedc\\\\desktop\\\\events.csv&quot;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-result-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-result-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">    |&gt; Result.map openCsv<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-result-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-result-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">    |&gt; Result.bind readRowsAndClose<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-result-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-result-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">    |&gt; Result.map getIds<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/137e02d6b103c36646330d9bc85da341/raw/8e6fa76000549a8ead1002e198911c4d9bced85c/result.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/137e02d6b103c36646330d9bc85da341#file-result-fs\" class=\"Link--inTextBlock\">\n          result.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div>



<p>When run via FSI, and given the input file above, this now produces:</p>



<p><code>val result : Result = Ok { Start = 1928<br>End = 1939 }</code></p>



<p>If we pass an invalid filename, we get a nice error:</p>



<p><code>val result : Result =<br>Error<br>(IO<br>("Could not open file",<br>System.IO.FileNotFoundException: Could not find file...</code></p>



<p>If we pass a good filename, but the file has bad data, that is also handled:</p>



<p><code>val result : Result =<br>Error<br>(DataMalformed<br>("Unable to parse data",<br>CsvHelper.TypeConversion.TypeConverterException: The conversion cannot be performed.<br>Text: '193d3'</code></p>



<p>By breaking this into pieces, and using Result.map and Result.bind, we were able to parse this in stages, where every stage could assume everything was &#8220;good&#8221;, and our errors propagate through cleanly at the end. Each step in the chain only has to focus on the task at hand.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2020/12/17/f-basics-result/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>F# Basics &#8211; From loops to folds</title>
		<link>http://reedcopsey.com/2019/12/19/f-basics-from-loops-to-folds/</link>
					<comments>http://reedcopsey.com/2019/12/19/f-basics-from-loops-to-folds/#respond</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Fri, 20 Dec 2019 03:41:52 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/?p=430</guid>

					<description><![CDATA[Instead of writing about Christmas trees this year, like I have for the last few years of FsAdvent, I thought I&#8217;d do a post about a topic that seems to frequently arise on the F# Software Foundation slack #beginners channel &#8211; looping and folds. People coming to F# from other languages frequently find themselves copying [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Instead of writing about Christmas trees this year, like I have for the last few years of <a href="https://sergeytihon.com/2019/11/05/f-advent-calendar-in-english-2019/">FsAdvent</a>, I thought I&#8217;d do a post about a topic that seems to frequently arise on the F# Software Foundation slack #beginners channel &#8211; looping and folds.</p>



<p>People coming to F# from other languages frequently find themselves copying the idioms of their past, and struggling with how to have things make sense in F#. Loops are a very common example.</p>



<p>A common thread in these discussions which seem to cause difficulty is &#8220;looping to generate a result&#8221;. This can be seen easily in the <a href="https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/intro-to-csharp/branches-and-loops?tutorial-step=6">C# tutorial&#8217;s looping code</a>. Here, a mutable value is created to hold some result (sum), a for loop iterates through a bunch of numbers, logic is placed in the loop body that mutates the value, and the result is used afterwards. While this can be ported to F# directly, it tends to be ugly in the end, as it relies on looping and on mutation.</p>



<style> #wrap_githubgist4813b05b77d180cebaa71609289351c8 .gist-data {max-height: 100%;} </style><div id="wrap_githubgist4813b05b77d180cebaa71609289351c8" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist100150538\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-csharp_coding_challenge-cs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-c  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"csharp_coding_challenge.cs content, created by ReedCopsey on 09:32PM on December 19, 2019.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"csharp_coding_challenge.cs\">\n        <tr>\n          <td id=\"file-csharp_coding_challenge-cs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-csharp_coding_challenge-cs-LC1\" class=\"blob-code blob-code-inner js-file-line\">int sum = 0;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-csharp_coding_challenge-cs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-csharp_coding_challenge-cs-LC2\" class=\"blob-code blob-code-inner js-file-line\">for (int number = 1; number &lt; 21; number++)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-csharp_coding_challenge-cs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-csharp_coding_challenge-cs-LC3\" class=\"blob-code blob-code-inner js-file-line\">{<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-csharp_coding_challenge-cs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-csharp_coding_challenge-cs-LC4\" class=\"blob-code blob-code-inner js-file-line\">  if (number % 3 == 0)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-csharp_coding_challenge-cs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-csharp_coding_challenge-cs-LC5\" class=\"blob-code blob-code-inner js-file-line\">  {<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-csharp_coding_challenge-cs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-csharp_coding_challenge-cs-LC6\" class=\"blob-code blob-code-inner js-file-line\">    sum = sum + number;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-csharp_coding_challenge-cs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-csharp_coding_challenge-cs-LC7\" class=\"blob-code blob-code-inner js-file-line\">  }<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-csharp_coding_challenge-cs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-csharp_coding_challenge-cs-LC8\" class=\"blob-code blob-code-inner js-file-line\">}<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-csharp_coding_challenge-cs-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-csharp_coding_challenge-cs-LC9\" class=\"blob-code blob-code-inner js-file-line\">Console.WriteLine(\$&quot;The sum is {sum}&quot;);<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/4813b05b77d180cebaa71609289351c8/raw/d64f6c3be73e18e981da1dcccaa7aca3ab6d9022/csharp_coding_challenge.cs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/4813b05b77d180cebaa71609289351c8#file-csharp_coding_challenge-cs\" class=\"Link--inTextBlock\">\n          csharp_coding_challenge.cs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div>



<p>I frequently suggest that people new to F# should strive to reduce mutation as well as code which relies on side effects (every loop body does), but confusion frequently occurs with cases like this. Recursion is frequently suggested as a solution, but its far from simple in many cases, especially when people are just starting out.</p>



<p>So let&#8217;s rework this a bit &#8211; and lets start small by reducing mutation. First off, we can refactor the &#8220;logic&#8221; portion of this into a function and make it pure. In this case, we want a function which will not mutate a value, but instead, return a <em>new </em>value each time it&#8217;s run, passing the existing input into it.</p>



<style> #wrap_githubgist4813b05b77d180cebaa71609289351c8 .gist-data {max-height: 100%;} </style><div id="wrap_githubgist4813b05b77d180cebaa71609289351c8" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist100150538\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-csharp_coding_challenge_factored-cs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-c  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"csharp_coding_challenge_factored.cs content, created by ReedCopsey on 09:32PM on December 19, 2019.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"csharp_coding_challenge_factored.cs\">\n        <tr>\n          <td id=\"file-csharp_coding_challenge_factored-cs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-csharp_coding_challenge_factored-cs-LC1\" class=\"blob-code blob-code-inner js-file-line\">int AddNewConditionally(int last, int number)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-csharp_coding_challenge_factored-cs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-csharp_coding_challenge_factored-cs-LC2\" class=\"blob-code blob-code-inner js-file-line\">{<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-csharp_coding_challenge_factored-cs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-csharp_coding_challenge_factored-cs-LC3\" class=\"blob-code blob-code-inner js-file-line\">    if(number % 3 == 0)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-csharp_coding_challenge_factored-cs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-csharp_coding_challenge_factored-cs-LC4\" class=\"blob-code blob-code-inner js-file-line\">        return last + number;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-csharp_coding_challenge_factored-cs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-csharp_coding_challenge_factored-cs-LC5\" class=\"blob-code blob-code-inner js-file-line\">    else<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-csharp_coding_challenge_factored-cs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-csharp_coding_challenge_factored-cs-LC6\" class=\"blob-code blob-code-inner js-file-line\">        return last;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-csharp_coding_challenge_factored-cs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-csharp_coding_challenge_factored-cs-LC7\" class=\"blob-code blob-code-inner js-file-line\">}<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-csharp_coding_challenge_factored-cs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-csharp_coding_challenge_factored-cs-LC8\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-csharp_coding_challenge_factored-cs-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-csharp_coding_challenge_factored-cs-LC9\" class=\"blob-code blob-code-inner js-file-line\">int sum = 0;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-csharp_coding_challenge_factored-cs-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-csharp_coding_challenge_factored-cs-LC10\" class=\"blob-code blob-code-inner js-file-line\">for (int number = 1; number &lt; 21; number++)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-csharp_coding_challenge_factored-cs-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-csharp_coding_challenge_factored-cs-LC11\" class=\"blob-code blob-code-inner js-file-line\">{<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-csharp_coding_challenge_factored-cs-L12\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"12\"><\/td>\n          <td id=\"file-csharp_coding_challenge_factored-cs-LC12\" class=\"blob-code blob-code-inner js-file-line\">    sum = AddNewConditionally(sum, number);<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-csharp_coding_challenge_factored-cs-L13\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"13\"><\/td>\n          <td id=\"file-csharp_coding_challenge_factored-cs-LC13\" class=\"blob-code blob-code-inner js-file-line\">}<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-csharp_coding_challenge_factored-cs-L14\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"14\"><\/td>\n          <td id=\"file-csharp_coding_challenge_factored-cs-LC14\" class=\"blob-code blob-code-inner js-file-line\">Console.WriteLine(\$&quot;The sum is {sum}&quot;);<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/4813b05b77d180cebaa71609289351c8/raw/d64f6c3be73e18e981da1dcccaa7aca3ab6d9022/csharp_coding_challenge_factored.cs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/4813b05b77d180cebaa71609289351c8#file-csharp_coding_challenge_factored-cs\" class=\"Link--inTextBlock\">\n          csharp_coding_challenge_factored.cs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div>



<p>Doing this allows the &#8220;logic&#8221; to be much more easily tested, but is also an important first step. We can then remove another point of mutation &#8211; the for loop itself, by switching to a foreach loop over a sequence:</p>



<style> #wrap_githubgist4813b05b77d180cebaa71609289351c8 .gist-data {max-height: 100%;} </style><div id="wrap_githubgist4813b05b77d180cebaa71609289351c8" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist100150538\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-csharp_for_to_foreach-cs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-c  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"csharp_for_to_foreach.cs content, created by ReedCopsey on 09:32PM on December 19, 2019.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"csharp_for_to_foreach.cs\">\n        <tr>\n          <td id=\"file-csharp_for_to_foreach-cs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-csharp_for_to_foreach-cs-LC1\" class=\"blob-code blob-code-inner js-file-line\">foreach (var number in Enumerable.Range(1,20))<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-csharp_for_to_foreach-cs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-csharp_for_to_foreach-cs-LC2\" class=\"blob-code blob-code-inner js-file-line\">{<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-csharp_for_to_foreach-cs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-csharp_for_to_foreach-cs-LC3\" class=\"blob-code blob-code-inner js-file-line\">    sum = AddNewConditionally(sum, number);<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-csharp_for_to_foreach-cs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-csharp_for_to_foreach-cs-LC4\" class=\"blob-code blob-code-inner js-file-line\">}<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/4813b05b77d180cebaa71609289351c8/raw/d64f6c3be73e18e981da1dcccaa7aca3ab6d9022/csharp_for_to_foreach.cs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/4813b05b77d180cebaa71609289351c8#file-csharp_for_to_foreach-cs\" class=\"Link--inTextBlock\">\n          csharp_for_to_foreach.cs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div>



<p>It&#8217;s typically at this point where people get stuck. Its far less obvious to see how we remove the mutable value which holds the result. Before we move forward with removing the mutation, lets port this to F#:</p>



<style> #wrap_githubgist4813b05b77d180cebaa71609289351c8 .gist-data {max-height: 100%;} </style><div id="wrap_githubgist4813b05b77d180cebaa71609289351c8" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist100150538\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-fsharp_ported_with_loop-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"fsharp_ported_with_loop.fs content, created by ReedCopsey on 09:32PM on December 19, 2019.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"fsharp_ported_with_loop.fs\">\n        <tr>\n          <td id=\"file-fsharp_ported_with_loop-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-fsharp_ported_with_loop-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">let addNewConditionally last number =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_ported_with_loop-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-fsharp_ported_with_loop-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">    if number % 3 = 0 then last + number else last<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_ported_with_loop-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-fsharp_ported_with_loop-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_ported_with_loop-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-fsharp_ported_with_loop-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">let mutable sum = 0<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_ported_with_loop-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-fsharp_ported_with_loop-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">for number in { 1..20 } do<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_ported_with_loop-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-fsharp_ported_with_loop-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">    sum &lt;- addNewConditionally sum number<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_ported_with_loop-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-fsharp_ported_with_loop-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_ported_with_loop-fs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-fsharp_ported_with_loop-fs-LC8\" class=\"blob-code blob-code-inner js-file-line\">printfn &quot;The sum is %d&quot; sum<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/4813b05b77d180cebaa71609289351c8/raw/d64f6c3be73e18e981da1dcccaa7aca3ab6d9022/fsharp_ported_with_loop.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/4813b05b77d180cebaa71609289351c8#file-fsharp_ported_with_loop-fs\" class=\"Link--inTextBlock\">\n          fsharp_ported_with_loop.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div>



<p>While this is obviously more succinct, it does exactly the same thing, using the same imperative techniques as before, at least in the core loop. In preparation to eliminate the mutation, I&#8217;m going to make this less succinct, so the <em>intention </em>behind what is occuring becomes more obvious.</p>



<style> #wrap_githubgist4813b05b77d180cebaa71609289351c8 .gist-data {max-height: 100%;} </style><div id="wrap_githubgist4813b05b77d180cebaa71609289351c8" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist100150538\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-fsharp_loop_with_steps-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"fsharp_loop_with_steps.fs content, created by ReedCopsey on 09:32PM on December 19, 2019.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"fsharp_loop_with_steps.fs\">\n        <tr>\n          <td id=\"file-fsharp_loop_with_steps-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-fsharp_loop_with_steps-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">let addNewConditionally last number =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_loop_with_steps-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-fsharp_loop_with_steps-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">    if number % 3 = 0 then last + number else last<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_loop_with_steps-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-fsharp_loop_with_steps-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_loop_with_steps-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-fsharp_loop_with_steps-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">// Start with &quot;0&quot;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_loop_with_steps-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-fsharp_loop_with_steps-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">let startingValue = 0<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_loop_with_steps-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-fsharp_loop_with_steps-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_loop_with_steps-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-fsharp_loop_with_steps-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">let valuesToProcess = { 1 .. 20 }<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_loop_with_steps-fs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-fsharp_loop_with_steps-fs-LC8\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_loop_with_steps-fs-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-fsharp_loop_with_steps-fs-LC9\" class=\"blob-code blob-code-inner js-file-line\">// Make a value we can increment as we loop<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_loop_with_steps-fs-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-fsharp_loop_with_steps-fs-LC10\" class=\"blob-code blob-code-inner js-file-line\">let mutable runningValue = startingValue<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_loop_with_steps-fs-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-fsharp_loop_with_steps-fs-LC11\" class=\"blob-code blob-code-inner js-file-line\">for number in valuesToProcess do<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_loop_with_steps-fs-L12\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"12\"><\/td>\n          <td id=\"file-fsharp_loop_with_steps-fs-LC12\" class=\"blob-code blob-code-inner js-file-line\">    // Adjust this each step<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_loop_with_steps-fs-L13\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"13\"><\/td>\n          <td id=\"file-fsharp_loop_with_steps-fs-LC13\" class=\"blob-code blob-code-inner js-file-line\">    runningValue &lt;- addNewConditionally runningValue number<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_loop_with_steps-fs-L14\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"14\"><\/td>\n          <td id=\"file-fsharp_loop_with_steps-fs-LC14\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_loop_with_steps-fs-L15\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"15\"><\/td>\n          <td id=\"file-fsharp_loop_with_steps-fs-LC15\" class=\"blob-code blob-code-inner js-file-line\">// Get the result at the end<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_loop_with_steps-fs-L16\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"16\"><\/td>\n          <td id=\"file-fsharp_loop_with_steps-fs-LC16\" class=\"blob-code blob-code-inner js-file-line\">let sum = runningValue<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_loop_with_steps-fs-L17\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"17\"><\/td>\n          <td id=\"file-fsharp_loop_with_steps-fs-LC17\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_loop_with_steps-fs-L18\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"18\"><\/td>\n          <td id=\"file-fsharp_loop_with_steps-fs-LC18\" class=\"blob-code blob-code-inner js-file-line\">printfn &quot;The sum is %d&quot; sum<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/4813b05b77d180cebaa71609289351c8/raw/d64f6c3be73e18e981da1dcccaa7aca3ab6d9022/fsharp_loop_with_steps.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/4813b05b77d180cebaa71609289351c8#file-fsharp_loop_with_steps-fs\" class=\"Link--inTextBlock\">\n          fsharp_loop_with_steps.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div>



<p>While this does the same steps as the previous version, each temporary value is broken out into a binding, so the intent and process becomes more clear. However, we still are using a mutable to hold and mutate state each step. </p>



<p>Enter fold.</p>



<p>If we look at <a href="https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/seq.fold%5B't%2C'state%5D-function-%5Bfsharp%5D">Seq.fold</a>, we see that it has the following signature:</p>



<style> #wrap_githubgist4813b05b77d180cebaa71609289351c8 .gist-data {max-height: 100%;} </style><div id="wrap_githubgist4813b05b77d180cebaa71609289351c8" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist100150538\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-seq-fold\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-text  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"Seq.fold content, created by ReedCopsey on 09:32PM on December 19, 2019.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"Seq.fold\">\n        <tr>\n          <td id=\"file-seq-fold-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-seq-fold-LC1\" class=\"blob-code blob-code-inner js-file-line\">Seq.fold : (&#39;State -&gt; &#39;T -&gt; &#39;State) -&gt; &#39;State -&gt; seq&lt;&#39;T&gt; -&gt; &#39;State<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/4813b05b77d180cebaa71609289351c8/raw/d64f6c3be73e18e981da1dcccaa7aca3ab6d9022/Seq.fold\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/4813b05b77d180cebaa71609289351c8#file-seq-fold\" class=\"Link--inTextBlock\">\n          Seq.fold\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div>



<p>This function takes a function as input, which takes the previous state, the current value, and returns the new state. That is remarkably similar looking to our factoring of addNewConditionally &#8211; it takes the last value, the current value, and returns the new value. It also then takes a &#8216;State value &#8211; which is the initial state used for the first item being processed. Finally, it takes a sequence to operate over, and then returns a result at the end after processing each item.</p>



<p>In our case, we have all three of these, so we can easily rewrite our loop as a fold:</p>



<style> #wrap_githubgist4813b05b77d180cebaa71609289351c8 .gist-data {max-height: 100%;} </style><div id="wrap_githubgist4813b05b77d180cebaa71609289351c8" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist100150538\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-fsharp_fold-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"fsharp_fold.fs content, created by ReedCopsey on 09:32PM on December 19, 2019.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"fsharp_fold.fs\">\n        <tr>\n          <td id=\"file-fsharp_fold-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-fsharp_fold-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">let addNewConditionally last number =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_fold-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-fsharp_fold-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">    if number % 3 = 0 then last + number else last<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_fold-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-fsharp_fold-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_fold-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-fsharp_fold-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">// Start with &quot;0&quot;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_fold-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-fsharp_fold-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">let startingValue = 0<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_fold-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-fsharp_fold-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_fold-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-fsharp_fold-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">let valuesToProcess = { 1 .. 20 }<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_fold-fs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-fsharp_fold-fs-LC8\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_fold-fs-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-fsharp_fold-fs-LC9\" class=\"blob-code blob-code-inner js-file-line\">// Fold instead of looping<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_fold-fs-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-fsharp_fold-fs-LC10\" class=\"blob-code blob-code-inner js-file-line\">let sum = Seq.fold addNewConditionally startingValue valuesToProcess<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_fold-fs-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-fsharp_fold-fs-LC11\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_fold-fs-L12\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"12\"><\/td>\n          <td id=\"file-fsharp_fold-fs-LC12\" class=\"blob-code blob-code-inner js-file-line\">printfn &quot;The sum is %d&quot; sum<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/4813b05b77d180cebaa71609289351c8/raw/d64f6c3be73e18e981da1dcccaa7aca3ab6d9022/fsharp_fold.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/4813b05b77d180cebaa71609289351c8#file-fsharp_fold-fs\" class=\"Link--inTextBlock\">\n          fsharp_fold.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div>



<p>Note that this eliminates the need for a mutable value &#8211; each step works on the previous result, and returns a new value. We can now remove all of the temporaries, and rewrite this much more simply:</p>



<style> #wrap_githubgist4813b05b77d180cebaa71609289351c8 .gist-data {max-height: 100%;} </style><div id="wrap_githubgist4813b05b77d180cebaa71609289351c8" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist100150538\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-fsharp_fold_final-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"fsharp_fold_final.fs content, created by ReedCopsey on 09:32PM on December 19, 2019.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"fsharp_fold_final.fs\">\n        <tr>\n          <td id=\"file-fsharp_fold_final-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-fsharp_fold_final-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">let addNewConditionally last number =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_fold_final-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-fsharp_fold_final-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">    if number % 3 = 0 then last + number else last<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_fold_final-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-fsharp_fold_final-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_fold_final-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-fsharp_fold_final-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">let sum = { 1 .. 20 } |&gt; Seq.fold addNewConditionally 0<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_fold_final-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-fsharp_fold_final-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_fold_final-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-fsharp_fold_final-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">printfn &quot;The sum is %d&quot; sum<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/4813b05b77d180cebaa71609289351c8/raw/d64f6c3be73e18e981da1dcccaa7aca3ab6d9022/fsharp_fold_final.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/4813b05b77d180cebaa71609289351c8#file-fsharp_fold_final-fs\" class=\"Link--inTextBlock\">\n          fsharp_fold_final.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div>



<p>This gives us a simple, clean way to handle this example. </p>



<p>On a side note, in this particular case, the result type and input collection are all int values, and the initial value is the default value for int (0), so we have other, potentially simpler options. We could use <a href="https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/seq.reduce%5b't%5d-function-%5bfsharp%5d">Seq.reduce</a> instead, or a Seq.filter piped into a Seq.sum. However, looking back at fold, one benefit is that the &#8216;State type is separate from the input type &#8216;T. This means we can use a fold to replace <em>any</em> loop that is used to generate results based off the items being looped over, even if the types don&#8217;t match.</p>



<p>As a simple example, lets say our requirements change. Instead of just needing the sum of the values that meet our criteria, suppose we want to generate a list of the values as strings. All we need to do is change our function to work on and return a string list, and to change our initial &#8216;State value. </p>



<style> #wrap_githubgist4813b05b77d180cebaa71609289351c8 .gist-data {max-height: 100%;} </style><div id="wrap_githubgist4813b05b77d180cebaa71609289351c8" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist100150538\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-fsharp_fold_v2-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"fsharp_fold_v2.fs content, created by ReedCopsey on 09:32PM on December 19, 2019.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"fsharp_fold_v2.fs\">\n        <tr>\n          <td id=\"file-fsharp_fold_v2-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-fsharp_fold_v2-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">let buildListConditionally l number =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_fold_v2-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-fsharp_fold_v2-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">    if number % 3 = 0 then (string number)::l else l<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_fold_v2-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-fsharp_fold_v2-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_fold_v2-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-fsharp_fold_v2-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">let values = { 1 .. 20 } |&gt; Seq.fold buildListConditionally []<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_fold_v2-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-fsharp_fold_v2-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_fold_v2-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-fsharp_fold_v2-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">printfn &quot;The values are %A&quot; values<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-fsharp_fold_v2-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-fsharp_fold_v2-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">printfn &quot;The first value is \\&quot;%s\\&quot;&quot; (List.head values)<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/4813b05b77d180cebaa71609289351c8/raw/d64f6c3be73e18e981da1dcccaa7aca3ab6d9022/fsharp_fold_v2.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/4813b05b77d180cebaa71609289351c8#file-fsharp_fold_v2-fs\" class=\"Link--inTextBlock\">\n          fsharp_fold_v2.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div>



<p>This works the same way, but now we go from int seq to string list instead of to an int as our result.</p>



<p>While these are fairly simple and contrived examples, the approach taken here works for moving from any loop that generates &#8220;results&#8221; to a fold:</p>



<ul class="wp-block-list"><li>Make core logic a pure function (which can be a lambda expression) &#8211; which takes the previous result, the current value, and return a new state</li><li>Rework items being &#8220;processed&#8221; into a collection or sequence if using a &#8220;for&#8221; style loop</li><li>Remove the mutable &#8220;running value&#8221; and the loop, and replace with a call to fold</li></ul>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2019/12/19/f-basics-from-loops-to-folds/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>2018 Christmas Trees &#8211; Cross Platform Edition using Avalonia</title>
		<link>http://reedcopsey.com/2018/12/18/2018-christmas-trees-cross-platform-edition-using-avalonia/</link>
					<comments>http://reedcopsey.com/2018/12/18/2018-christmas-trees-cross-platform-edition-using-avalonia/#comments</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Tue, 18 Dec 2018 16:40:27 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/?p=409</guid>

					<description><![CDATA[For the last couple of years, my FsAdvent posts have focused around a simple, fun little Christmas Trees application illustrating the usage of Gjallarhorn.Bindable &#8211; and for this year, I thought I&#8217;d keep the streak going &#8211; with a twist. I&#8217;m happy to announce the availability of Gjallarhorn.Bindable.Avalonia, which allows Gjallarhorn to be used with [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>For the last couple of years, my <a href="https://sergeytihon.com/2018/10/22/f-advent-calendar-in-english-2018/">FsAdvent</a> posts have focused around a simple, fun little <a href="http://reedcopsey.com/2017/12/14/christmas-trees-in-wpf-2017-update/">Christmas Trees application</a> illustrating the usage of <a href="https://github.com/ReedCopsey/Gjallarhorn.Bindable">Gjallarhorn.Bindable</a> &#8211; and for this year, I thought I&#8217;d keep the streak going &#8211; with a twist. I&#8217;m happy to announce the availability of <a href="https://www.nuget.org/packages/Gjallarhorn.Bindable.Avalonia/">Gjallarhorn.Bindable.Avalonia</a>, which allows Gjallarhorn to be used with <a href="http://avaloniaui.net/">Avalonia</a>, the cross platform XAML based UI Framework.<span id="more-409"></span></p>



<p>For those familiar with last year&#8217;s <a href="http://reedcopsey.com/2017/12/14/christmas-trees-in-wpf-2017-update/">Christmas Trees application</a>, I wanted to start by saying I&#8217;ve only made two simple changes to the logic portion of that application, one by choice, one to make Avalonia function a bit better. </p>



<p>Since Avalonia is intended to run on multiple platforms, I thought it would make sense to simplify the interface. In previous years, I had separate logic for right and left mouse click events, which isn&#8217;t very friendly on Mac or mobile. To handle this, I thought I&#8217;d add a single &#8220;DecorateOrLight&#8221; command that would automatically toggle the decorated and lit state of the trees every time you clicked/tapped on a tree instead of having two separate operations.</p>



<p>Given the MVU approach Gjallarhorn uses, this was very simple. All I needed to do in the Tree handlers was add a single new case to the message, and handle it:</p>



<figure class="wp-block-image"><img fetchpriority="high" decoding="async" width="822" height="429" src="http://reedcopsey.com/blog/wp-content/uploads/2018/12/image.png" alt="" class="wp-image-411" srcset="http://reedcopsey.com/blog/wp-content/uploads/2018/12/image.png 822w, http://reedcopsey.com/blog/wp-content/uploads/2018/12/image-300x157.png 300w" sizes="(max-width: 822px) 100vw, 822px" /><figcaption><br></figcaption></figure>



<p>I also needed to modify the program in 2 places to add Commands to handle this new message:</p>



<p></p>



<figure class="wp-block-image"><img decoding="async" width="718" height="391" src="http://reedcopsey.com/blog/wp-content/uploads/2018/12/image-1.png" alt="" class="wp-image-412" srcset="http://reedcopsey.com/blog/wp-content/uploads/2018/12/image-1.png 718w, http://reedcopsey.com/blog/wp-content/uploads/2018/12/image-1-300x163.png 300w" sizes="(max-width: 718px) 100vw, 718px" /></figure>



<p>Once the design time support had this command, it was just a one line addition to bind this to a new command for the view layer.</p>



<p>The other change made to the logic portion was changing the Forest type to accept a Location option instead of a Location for adding new trees. In the WPF application, I was using some special FsXaml helpers to filter out &#8220;None&#8221; values, but the default XAML tooling doesn&#8217;t support that. Instead, I&#8217;m now filtering out None values in the Forest update method and leaving the forest unchanged:</p>



<figure class="wp-block-image"><img decoding="async" width="749" height="188" src="http://reedcopsey.com/blog/wp-content/uploads/2018/12/image-2.png" alt="" class="wp-image-413" srcset="http://reedcopsey.com/blog/wp-content/uploads/2018/12/image-2.png 749w, http://reedcopsey.com/blog/wp-content/uploads/2018/12/image-2-300x75.png 300w" sizes="(max-width: 749px) 100vw, 749px" /></figure>



<p>While this is a bit more code, it makes the logic not rely on WPF/FsXaml specific helpers. The WPF application only required on change (remove the filter-by-option setting from XAML) to work again.</p>



<p>Once these changes were in place, I was able to do the fun part &#8211; wire this up to Avalonia instead of WPF.</p>



<p>To get that working, I just made a new .NET Core application, and added <a href="https://www.nuget.org/packages/Gjallarhorn.Bindable.Avalonia/">Gjallarhorn.Bindable.Avalonia</a> as well as some helper routines (XAML Behaviors for Avalonia, etc). The XAML from WPF was copied then modified to work with Avalonia&#8217;s structure. While it is mostly unchanged, there are some differences in <a href="http://avaloniaui.net/docs/quickstart/from-wpf">Avalonia from WPF</a> to handle. I also added an App.xaml as this is expected by Avalonia. </p>



<p>With this done, the startup code in Gjallarhorn.Bindable for Avalonia is very similar to WPF. I modified what was used in WPF:<br><style> #wrap_githubgistccbe5494122d44dedd811a27b7084b63 .gist-data {max-height: 100%;} </style><div id="wrap_githubgistccbe5494122d44dedd811a27b7084b63" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist93638001\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-wpfview-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"WpfView.fs content, created by ReedCopsey on 04:36PM on December 18, 2018.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"WpfView.fs\">\n        <tr>\n          <td id=\"file-wpfview-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-wpfview-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">[&lt;STAThread&gt;]<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-wpfview-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-wpfview-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">[&lt;EntryPoint&gt;]<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-wpfview-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-wpfview-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">let main _ =  <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-wpfview-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-wpfview-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">	// Run using the WPF wrappers around the basic application framework    <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-wpfview-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-wpfview-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">	let nav = Gjallarhorn.Wpf.Navigation.singleView System.Windows.Application MainWindow<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-wpfview-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-wpfview-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">	let app = Program.application nav.Navigate<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-wpfview-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-wpfview-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">	Gjallarhorn.Wpf.Framework.RunApplication&lt;Forest,unit,ForestMessage&gt; (nav, app)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-wpfview-fs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-wpfview-fs-LC8\" class=\"blob-code blob-code-inner js-file-line\">	0<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/ccbe5494122d44dedd811a27b7084b63/raw/67078fc9a0b8fc734aeb8c377543d07cc4c3e645/WpfView.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/ccbe5494122d44dedd811a27b7084b63#file-wpfview-fs\" class=\"Link--inTextBlock\">\n          WpfView.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>



<p>To make this work in Avalonia, I do the avalonia configuration, then use a slightly modified version of the original WPF code:<br><style> #wrap_githubgistccbe5494122d44dedd811a27b7084b63 .gist-data {max-height: 100%;} </style><div id="wrap_githubgistccbe5494122d44dedd811a27b7084b63" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist93638001\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-avaloniaprogram-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"AvaloniaProgram.fs content, created by ReedCopsey on 04:36PM on December 18, 2018.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"AvaloniaProgram.fs\">\n        <tr>\n          <td id=\"file-avaloniaprogram-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-avaloniaprogram-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">[&lt;STAThread&gt;]<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-avaloniaprogram-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-avaloniaprogram-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">[&lt;EntryPoint&gt;]<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-avaloniaprogram-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-avaloniaprogram-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">let main _ =         <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-avaloniaprogram-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-avaloniaprogram-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">    let app () =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-avaloniaprogram-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-avaloniaprogram-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">        AppBuilder.Configure&lt;App&gt;().UsePlatformDetect().LogToDebug().SetupWithoutStarting().Instance                <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-avaloniaprogram-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-avaloniaprogram-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-avaloniaprogram-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-avaloniaprogram-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">    let nav = Gjallarhorn.Avalonia.Navigation.singleView app MainWindow<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-avaloniaprogram-fs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-avaloniaprogram-fs-LC8\" class=\"blob-code blob-code-inner js-file-line\">    let app&#39; = Program.application nav.Navigate<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-avaloniaprogram-fs-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-avaloniaprogram-fs-LC9\" class=\"blob-code blob-code-inner js-file-line\">         <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-avaloniaprogram-fs-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-avaloniaprogram-fs-LC10\" class=\"blob-code blob-code-inner js-file-line\">    Gjallarhorn.Avalonia.Framework.RunApplication&lt;Forest,unit,ForestMessage&gt; (nav, app&#39;)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-avaloniaprogram-fs-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-avaloniaprogram-fs-LC11\" class=\"blob-code blob-code-inner js-file-line\">    0<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/ccbe5494122d44dedd811a27b7084b63/raw/67078fc9a0b8fc734aeb8c377543d07cc4c3e645/AvaloniaProgram.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/ccbe5494122d44dedd811a27b7084b63#file-avaloniaprogram-fs\" class=\"Link--inTextBlock\">\n          AvaloniaProgram.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>



<p>With this in place, we can now run and make Christmas Trees using Avalonia!</p>



<p></p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="626" height="663" src="http://reedcopsey.com/blog/wp-content/uploads/2018/12/image-3.png" alt="" class="wp-image-417" srcset="http://reedcopsey.com/blog/wp-content/uploads/2018/12/image-3.png 626w, http://reedcopsey.com/blog/wp-content/uploads/2018/12/image-3-283x300.png 283w" sizes="(max-width: 626px) 100vw, 626px" /></figure>



<p>Even better, since this uses Avalonia and .NET Core, the same code works cleanly on other platforms. For example, here is the same code running on a Mac given nothing but a clone and dotnet run (and a special thank you to <a href="https://twitter.com/ChetHusk">@ChetHusk</a> for cloning and running this for me):</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="502" height="522" src="http://reedcopsey.com/blog/wp-content/uploads/2018/12/image-4.png" alt="" class="wp-image-418" srcset="http://reedcopsey.com/blog/wp-content/uploads/2018/12/image-4.png 502w, http://reedcopsey.com/blog/wp-content/uploads/2018/12/image-4-289x300.png 289w" sizes="(max-width: 502px) 100vw, 502px" /></figure>



<p><br></p>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2018/12/18/2018-christmas-trees-cross-platform-edition-using-avalonia/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Christmas Trees in WPF, 2017 Update</title>
		<link>http://reedcopsey.com/2017/12/14/christmas-trees-in-wpf-2017-update/</link>
					<comments>http://reedcopsey.com/2017/12/14/christmas-trees-in-wpf-2017-update/#comments</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Fri, 15 Dec 2017 06:05:03 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/?p=398</guid>

					<description><![CDATA[Last year, I wrote about making Christmas Trees in WPF using Gjallarhorn. The Gjallarhorn project has improved dramatically since last year, and I thought I&#8217;d update the project, demonstrating the newer API and significant improvements in usability and ease of development. I recommend skimming through the previous post, as this post expands on the information [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Last year, I wrote about making <a href="http://reedcopsey.com/2016/12/15/christmas-trees-in-wpf-2016-edition/">Christmas Trees in WPF using Gjallarhorn</a>. The Gjallarhorn project has improved dramatically since last year, and I thought I&#8217;d update the project, demonstrating the newer API and significant improvements in usability and ease of development. I recommend skimming through the previous post, as this post expands on the information there.</p>
<p>This post will modernize the <a href="https://github.com/ReedCopsey/AdventTrees2016">Christmas Tree</a>Â application from last year, improving it, and highlighting the changes in Gjallarhorn, showing the dramatic improvements inspired by great projects like <a href="https://fable-elmish.github.io/elmish/">Elmish</a>. My hope is that more developers will see the benefits of unidirectional architecture for UI development, and try using Elmish for web, Gjallarhorn for XAML, or other unidirectional, functional approaches to user interfaces.<span id="more-398"></span></p>
<p>Over the last year, <a href="https://github.com/reedcopsey/gjallarhorn">Gjallarhorn</a>Â has matured greatly. Earlier this year, the project reached the version 1.0 milestone, and the user interface framework was split off into it&#8217;s own project &#8211; <a href="https://github.com/reedcopsey/gjallarhorn.bindable">Gjallarhorn.Bindable</a>. Gjallarhorn.Bindable has taken inspiration from Elmish, and developed a newer, simpler API, which adds significant benefits.</p>
<p>The new API has been driven with a few distinct goals in mind. First off, we wanted to simplify the code required. We also wanted to improve type safety and eliminate magic strings whenever possible. Finally, many new scenarios have been enabled via the new navigation API, which allows applications to <em>cleanly</em>Â work with multiple windows, views, and more.</p>
<p>That being said, the model and message types, and update function, are completely unchanged. The changes all relate to the binding components and application framework setup.</p>
<p>The first major change in migrating to the new API is the addition of a &#8220;view model&#8221; type. This is a simple type (currently typically a record) used for multiple purposes &#8211; it enables design time data for the XAML designer (with type and error checking, intellisense, and more when using Resharper), it eliminates the magic strings in code, and it adds type checking to the binding generation. The &#8220;View Model&#8221; type is simply a record with one field per binding, used to create an instantiated binding of that record type. For example, our Tree binding from last year is now augmented with the following &#8220;VM&#8221; type and binding:</p>
<p><style> #wrap_githubgist7b871ed9f0f5c7f99cdc3190ace39d13 .gist-data {max-height: 100%;} </style><div id="wrap_githubgist7b871ed9f0f5c7f99cdc3190ace39d13" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist84276734\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-treevm-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"treevm.fs content, created by ReedCopsey on 05:23AM on December 15, 2017.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"treevm.fs\">\n        <tr>\n          <td id=\"file-treevm-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-treevm-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">type TreeVM =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treevm-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-treevm-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">    {<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treevm-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-treevm-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">        Tree     : Tree<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treevm-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-treevm-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">        Decorate : VmCmd&lt;TreeMessage&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treevm-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-treevm-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">        Light    : VmCmd&lt;TreeMessage&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treevm-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-treevm-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">    }<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treevm-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-treevm-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">let treeDesign = { Tree = { Position = { X = 0.0 ; Y = 0.0 } ; Height = 1.0 ; Decorated = true ; Lit = true } ; Decorate = Vm.cmd Decorate ; Light = Vm.cmd Light }<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/7b871ed9f0f5c7f99cdc3190ace39d13/raw/da1d1cdb5b5e6a06d3fbf880e9fc5428e37f2ff5/treevm.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/7b871ed9f0f5c7f99cdc3190ace39d13#file-treevm-fs\" class=\"Link--inTextBlock\">\n          treevm.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>The VmCmd type here is provided by Gjallarhorn.Bindable, and allows you to represent a typed message which will be sent back to the update function. Any command bound to the view will be represented this way.</p>
<p>One side note: the current design for the VM was created with the <a href="https://github.com/fsharp/fslang-design/blob/master/RFCs/FS-1030-anonymous-records.md">proposed anonymous records</a> kept in mind. If implemented as currently proposed and approved in principle, anonymous records will, in most cases, eliminate the need to create the VM as a type &#8211; a simple binding with an anonymous record will work, making this a one-line addition over the previous API.</p>
<p>Once the VM binding exists, it can be used via the new Gjallarhorn API to create our binding much simpler than the previous mechanism. Previously, the tree component was created like so:</p>
<p><style> #wrap_githubgistf18b683b9d8d25056ebf70087c522390 .gist-data {max-height: 100%;} </style><div id="wrap_githubgistf18b683b9d8d25056ebf70087c522390" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist42896112\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-treecomponent2-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"treeComponent2.fs content, created by ReedCopsey on 01:08AM on December 15, 2016.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"treeComponent2.fs\">\n        <tr>\n          <td id=\"file-treecomponent2-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-treecomponent2-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">let treeComponent source (model : ISignal&lt;Tree&gt;) =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent2-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-treecomponent2-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">    model |&gt; Binding.toView source &quot;Tree&quot;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent2-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-treecomponent2-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent2-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-treecomponent2-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">    [        <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent2-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-treecomponent2-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">        source |&gt; Binding.createMessage &quot;Decorate&quot; Decorate <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent2-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-treecomponent2-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">        // Add one line here to add a new command that maps to the light message<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent2-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-treecomponent2-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">        source |&gt; Binding.createMessage &quot;Light&quot; Light<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent2-fs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-treecomponent2-fs-LC8\" class=\"blob-code blob-code-inner js-file-line\">    ]<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390/raw/d2a4c06d08d82dda677d941054a7e02e7c3a6236/treeComponent2.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390#file-treecomponent2-fs\" class=\"Link--inTextBlock\">\n          treeComponent2.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>With the new VM and new API, this is significantly simpler:</p>
<p><style> #wrap_githubgist7b871ed9f0f5c7f99cdc3190ace39d13 .gist-data {max-height: 100%;} </style><div id="wrap_githubgist7b871ed9f0f5c7f99cdc3190ace39d13" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist84276734\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-treecomponent-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"treeComponent.fs content, created by ReedCopsey on 05:23AM on December 15, 2017.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"treeComponent.fs\">\n        <tr>\n          <td id=\"file-treecomponent-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-treecomponent-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">let treeComponent =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-treecomponent-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">        Component.create&lt;Tree,unit,TreeMessage&gt; [<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-treecomponent-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">            &lt;@ treeDesign.Tree @&gt;     |&gt; Bind.oneWay id<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-treecomponent-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">            &lt;@ treeDesign.Decorate @&gt; |&gt; Bind.cmd<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-treecomponent-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">            &lt;@ treeDesign.Light @&gt;    |&gt; Bind.cmd<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-treecomponent-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">        ]<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/7b871ed9f0f5c7f99cdc3190ace39d13/raw/da1d1cdb5b5e6a06d3fbf880e9fc5428e37f2ff5/treeComponent.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/7b871ed9f0f5c7f99cdc3190ace39d13#file-treecomponent-fs\" class=\"Link--inTextBlock\">\n          treeComponent.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>Note that the magic strings used before have been replaced with quotations. In addition, the types defined in the VM are used to type check the bindings directly. We also no longer need to worry or think about the internal types in Gjallarhorn &#8211; the BindingSource and ISignal types are eliminated, and we directly specify a mapping from the model type to the bound value type as a simple function (in this case, id, as we&#8217;re binding the model directly).</p>
<p>(The unit generic type here refers to the Navigation types &#8211; as we are not enabling any navigation messages, I&#8217;m passing unit through this everywhere, to effectively ignore the navigation options.)</p>
<p>Our Forest component gets the same treatment:</p>
<p><style> #wrap_githubgist7b871ed9f0f5c7f99cdc3190ace39d13 .gist-data {max-height: 100%;} </style><div id="wrap_githubgist7b871ed9f0f5c7f99cdc3190ace39d13" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist84276734\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-forestcomponent-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"forestComponent.fs content, created by ReedCopsey on 05:23AM on December 15, 2017.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"forestComponent.fs\">\n        <tr>\n          <td id=\"file-forestcomponent-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-forestcomponent-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">// Create binding for entire application.  This will output all of our messages.<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forestcomponent-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-forestcomponent-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">let forestComponent =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forestcomponent-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-forestcomponent-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">    Component.create&lt;Forest,unit,ForestMessage&gt; [<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forestcomponent-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-forestcomponent-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">        &lt;@ forestDesign.Forest @&gt; |&gt; Bind.collection id treeComponent UpdateTree<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forestcomponent-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-forestcomponent-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">        &lt;@ forestDesign.Add @&gt;    |&gt; Bind.cmdParam Add<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forestcomponent-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-forestcomponent-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">    ]<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/7b871ed9f0f5c7f99cdc3190ace39d13/raw/da1d1cdb5b5e6a06d3fbf880e9fc5428e37f2ff5/forestComponent.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/7b871ed9f0f5c7f99cdc3190ace39d13#file-forestcomponent-fs\" class=\"Link--inTextBlock\">\n          forestComponent.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>In addition, the main &#8220;Application&#8221; components have been simplified. In last year&#8217;s version, we managed state ourselves. An AsyncMutable&lt;&#8216;a&gt; from Gjallarhorn was manually created to hold the application state, and an initialization function started an infinite loop to externally update the model state as needed.</p>
<p>The new API simplifies this. The application now takes an initial state, and external updates are now managed via formalized patterns and types defined in the framework. For our pruning routine, instead of directly manipulating the global model, we now create a function which can produce and dispatch messages via a Dispatch&lt;&#8216;a&gt; type passed in, which is simply a function that&#8217;s &#8216;Msg -&gt; unit.</p>
<p><style> #wrap_githubgist7b871ed9f0f5c7f99cdc3190ace39d13 .gist-data {max-height: 100%;} </style><div id="wrap_githubgist7b871ed9f0f5c7f99cdc3190ace39d13" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist84276734\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-prunehandler-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"pruneHandler.fs content, created by ReedCopsey on 05:23AM on December 15, 2017.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"pruneHandler.fs\">\n        <tr>\n          <td id=\"file-prunehandler-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-prunehandler-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">let pruneHandler (dispatch : Dispatch&lt;_&gt;) token =        <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prunehandler-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-prunehandler-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">    // Handle pruning of the forest - <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prunehandler-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-prunehandler-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">    // Twice per second, send a prune message to remove a tree if there are more than max<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prunehandler-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-prunehandler-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">    let rec pruneForever max =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prunehandler-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-prunehandler-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">        async {<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prunehandler-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-prunehandler-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">            do! Async.Sleep 500                <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prunehandler-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-prunehandler-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">            Prune max |&gt; dispatch<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prunehandler-fs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-prunehandler-fs-LC8\" class=\"blob-code blob-code-inner js-file-line\">            return! pruneForever max <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prunehandler-fs-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-prunehandler-fs-LC9\" class=\"blob-code blob-code-inner js-file-line\">        }<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prunehandler-fs-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-prunehandler-fs-LC10\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prunehandler-fs-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-prunehandler-fs-LC11\" class=\"blob-code blob-code-inner js-file-line\">    // Start prune loop in the background asynchronously<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-prunehandler-fs-L12\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"12\"><\/td>\n          <td id=\"file-prunehandler-fs-LC12\" class=\"blob-code blob-code-inner js-file-line\">    Async.Start(pruneForever 10, token)<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/7b871ed9f0f5c7f99cdc3190ace39d13/raw/da1d1cdb5b5e6a06d3fbf880e9fc5428e37f2ff5/pruneHandler.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/7b871ed9f0f5c7f99cdc3190ace39d13#file-prunehandler-fs\" class=\"Link--inTextBlock\">\n          pruneHandler.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>With this, we can create an &#8220;Executor&#8221; &#8211; which is a Gjallarhorn type which can be used to start and stop asynchronous, external (unrelated to the UI) operations. The application framework is dramatically simplified &#8211; instead of managing state, we just pass in the initial state, update, view component, and navigation dispatcher (unused in this application). We then attach our executor, and the framework takes care of all of the state management in a thread safe, clean manner:</p>
<p><style> #wrap_githubgist7b871ed9f0f5c7f99cdc3190ace39d13 .gist-data {max-height: 100%;} </style><div id="wrap_githubgist7b871ed9f0f5c7f99cdc3190ace39d13" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist84276734\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-app-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"app.fs content, created by ReedCopsey on 05:23AM on December 15, 2017.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"app.fs\">\n        <tr>\n          <td id=\"file-app-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-app-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">let application nav =       <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-app-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-app-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">    // Start pruning &quot;loop&quot; via Executor type<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-app-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-app-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">    let prune = new Executor&lt;_,_&gt;(pruneHandler)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-app-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-app-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">    prune.Start()<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-app-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-app-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">    // Start our application, and attach the executor so messages dispatch to the application<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-app-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-app-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">    Framework.application Forest.empty Forest.update forestComponent nav<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-app-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-app-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">    |&gt; Framework.withDispatcher prune<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/7b871ed9f0f5c7f99cdc3190ace39d13/raw/da1d1cdb5b5e6a06d3fbf880e9fc5428e37f2ff5/app.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/7b871ed9f0f5c7f99cdc3190ace39d13#file-app-fs\" class=\"Link--inTextBlock\">\n          app.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>Not only is this far simpler and more concise (7 lines of code vs 25), it eliminates most of the major potential for mistakes. The focus moves away from working with types defined in Gjallarhorn (mutables and signals) to focusing on the model, message, and update function. External operations can be attached easily, in a predictable manner. The same pattern also allows for logging and other scenarios to be managed in a formalized, simple manner.</p>
<p>The final change required to update this application is in the WPF project. Gjallarhorn.Bindable now supports navigation, which requires some minor changes. Our new entry point function is now:</p>
<p><style> #wrap_githubgist7b871ed9f0f5c7f99cdc3190ace39d13 .gist-data {max-height: 100%;} </style><div id="wrap_githubgist7b871ed9f0f5c7f99cdc3190ace39d13" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist84276734\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-main-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"main.fs content, created by ReedCopsey on 05:23AM on December 15, 2017.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"main.fs\">\n        <tr>\n          <td id=\"file-main-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-main-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">let main _ =  <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-main-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-main-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">    // Run using the WPF wrappers around the basic application framework    <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-main-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-main-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">    let nav = Gjallarhorn.Wpf.Navigation.singleView System.Windows.Application MainWindow<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-main-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-main-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">    let app = Program.application nav.Navigate<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-main-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-main-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">    Gjallarhorn.Wpf.Framework.RunApplication&lt;Forest,unit,ForestMessage&gt; (nav, app)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-main-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-main-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">    0<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/7b871ed9f0f5c7f99cdc3190ace39d13/raw/da1d1cdb5b5e6a06d3fbf880e9fc5428e37f2ff5/main.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/7b871ed9f0f5c7f99cdc3190ace39d13#file-main-fs\" class=\"Link--inTextBlock\">\n          main.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>For this application, we&#8217;re working in a single view in an single application, so we&#8217;re using the predefined &#8220;singleView&#8221; navigation type, and unit for the navigation message type. However, the framework supports other navigation types, including single page apps, and fully extendable, customizable navigation enabling multiple windows, each with multiple views, and other scenarios previously difficult to manage with unidirectional architectures.</p>
<p>When run, the new updated version produces the exact same runtime behavior as last year, but now our code is simpler, type safe, and focused more on our domain types and less on the framework enabling the user interface.</p>
<p>Please feel free to <a href="https://github.com/ReedCopsey/AdventTrees2016">clone the repository</a>, try the application, and play with the new and improved framework. Gjallarhorn is still evolving, but now provides a clean, cross platform, unidirectional approach to developing programs based on XAML platforms.</p>
<p>I also recommend reading the other <a href="https://sergeytihon.com/2017/10/22/f-advent-calendar-in-english-2017/">2017 F# Advent posts</a>Â being written by the amazing F# community!</p>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2017/12/14/christmas-trees-in-wpf-2017-update/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title>Christmas Trees in WPF, 2016 Edition</title>
		<link>http://reedcopsey.com/2016/12/15/christmas-trees-in-wpf-2016-edition/</link>
					<comments>http://reedcopsey.com/2016/12/15/christmas-trees-in-wpf-2016-edition/#comments</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Thu, 15 Dec 2016 20:22:16 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Async]]></category>
		<category><![CDATA[F#]]></category>
		<category><![CDATA[Gjallarhorn]]></category>
		<category><![CDATA[MVVM]]></category>
		<category><![CDATA[WPF]]></category>
		<category><![CDATA[WPF Gjallarhorn F#]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/?p=365</guid>

					<description><![CDATA[Last year, I wrote about making Christmas Trees in WPF using FSharp.ViewModule. Â At the time,Â I was excited being able to demonstrate howÂ FSharp.ViewModule could make typical MVVM much more functional feeling. Â This year, for my F# Advent Calendar contribution, I want to demonstrate how Gjallarhorn.BindingÂ can serve as a replacement, and help create a WPF application with [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Last year, I wrote about making <a href="http://reedcopsey.com/2015/12/09/christmas-trees-in-wpf-using-fsharp-viewmodule/">Christmas Trees in WPF using FSharp.ViewModule</a>. Â At the time,Â I was excited being able to demonstrate howÂ FSharp.ViewModule could make typical MVVM much more functional feeling. Â This year, for my <a href="https://sergeytihon.wordpress.com/tag/fsadvent/">F# Advent Calendar contribution</a>, I want to demonstrate how <a href="https://github.com/ReedCopsey/Gjallarhorn">Gjallarhorn.Binding</a>Â can serve as a replacement, and help create a WPF application with a design that is clean, functional, and most importantly, simple.</p>
<p>This post will modernize the <a href="http://reedcopsey.com/2015/12/09/christmas-trees-in-wpf-using-fsharp-viewmodule/">Christmas Tree</a>Â application from last year, improving it, and highlighting the differences between a classic MVVM approach to WPF and a more functional approach. Â While reading through the post from last year would add context, it&#8217;s completely optional.</p>
<p><span id="more-365"></span></p>
<p>As always, I&#8217;ll begin with a brief introduction to the model. Â I&#8217;ve taken the model from last year mostly as-is, except simplified it and made it more &#8220;idiomatic F#&#8221;. Â This year, I broke out the model for a Tree into its own file:</p>
<p><style> #wrap_githubgistf18b683b9d8d25056ebf70087c522390 .gist-data {max-height: 100%;} </style><div id="wrap_githubgistf18b683b9d8d25056ebf70087c522390" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist42896112\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-tree-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"tree.fs content, created by ReedCopsey on 01:08AM on December 15, 2016.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"tree.fs\">\n        <tr>\n          <td id=\"file-tree-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-tree-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">// Our tree types<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-tree-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">type Location = { X: float; Y: float }<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-tree-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">type Tree = { Position : Location ; Height : float ; Decorated : bool }<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-tree-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-tree-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">// Update types allowed on a tree<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-tree-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">type TreeMessage = | Decorate<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-tree-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree-fs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-tree-fs-LC8\" class=\"blob-code blob-code-inner js-file-line\">// Module showing allowed operations on an existing tree<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree-fs-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-tree-fs-LC9\" class=\"blob-code blob-code-inner js-file-line\">[&lt;CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)&gt;]<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree-fs-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-tree-fs-LC10\" class=\"blob-code blob-code-inner js-file-line\">module Tree =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree-fs-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-tree-fs-LC11\" class=\"blob-code blob-code-inner js-file-line\">    let private rnd = System.Random()<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree-fs-L12\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"12\"><\/td>\n          <td id=\"file-tree-fs-LC12\" class=\"blob-code blob-code-inner js-file-line\">    let private makeHeight () = 8.0 + rnd.NextDouble() * 4.0<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree-fs-L13\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"13\"><\/td>\n          <td id=\"file-tree-fs-LC13\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree-fs-L14\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"14\"><\/td>\n          <td id=\"file-tree-fs-LC14\" class=\"blob-code blob-code-inner js-file-line\">    let create location = <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree-fs-L15\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"15\"><\/td>\n          <td id=\"file-tree-fs-LC15\" class=\"blob-code blob-code-inner js-file-line\">        { Position = location ; Height = makeHeight () ; Decorated = false }<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree-fs-L16\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"16\"><\/td>\n          <td id=\"file-tree-fs-LC16\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree-fs-L17\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"17\"><\/td>\n          <td id=\"file-tree-fs-LC17\" class=\"blob-code blob-code-inner js-file-line\">    let update msg tree =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree-fs-L18\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"18\"><\/td>\n          <td id=\"file-tree-fs-LC18\" class=\"blob-code blob-code-inner js-file-line\">        match msg with<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree-fs-L19\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"19\"><\/td>\n          <td id=\"file-tree-fs-LC19\" class=\"blob-code blob-code-inner js-file-line\">        | Decorate -&gt; { tree with Decorated = true }<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree-fs-L20\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"20\"><\/td>\n          <td id=\"file-tree-fs-LC20\" class=\"blob-code blob-code-inner js-file-line\">            <\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390/raw/d2a4c06d08d82dda677d941054a7e02e7c3a6236/tree.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390#file-tree-fs\" class=\"Link--inTextBlock\">\n          tree.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>The actual Tree type is unchanged &#8211; but I&#8217;ve created the functions to create a new tree and update an existing tree, and placed them into a module for working with trees. Â This isolates the types and logic for dealing with a single tree into its own testable portion of the application, and is simple, easy to follow, and easily extensible.</p>
<p>The model for a Forest has received similar treatment:</p>
<p><style> #wrap_githubgistf18b683b9d8d25056ebf70087c522390 .gist-data {max-height: 100%;} </style><div id="wrap_githubgistf18b683b9d8d25056ebf70087c522390" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist42896112\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-forest-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"forest.fs content, created by ReedCopsey on 01:08AM on December 15, 2016.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"forest.fs\">\n        <tr>\n          <td id=\"file-forest-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-forest-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">// Our main forest model<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-forest-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">type Forest = Tree list<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-forest-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-forest-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">// Update types allowed on a forest<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-forest-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">type ForestMessage =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-forest-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">    | Add of Location // Add new tree at a location<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-forest-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">    | UpdateTree of msg : TreeMessage * tree : Tree // Update an existing tree<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-forest-fs-LC8\" class=\"blob-code blob-code-inner js-file-line\">    | Prune of maxTrees : int  // Prune the trees<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-forest-fs-LC9\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-forest-fs-LC10\" class=\"blob-code blob-code-inner js-file-line\">// Module with allowed operations on a forest<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-forest-fs-LC11\" class=\"blob-code blob-code-inner js-file-line\">[&lt;CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)&gt;]<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L12\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"12\"><\/td>\n          <td id=\"file-forest-fs-LC12\" class=\"blob-code blob-code-inner js-file-line\">module Forest =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L13\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"13\"><\/td>\n          <td id=\"file-forest-fs-LC13\" class=\"blob-code blob-code-inner js-file-line\">    let private rnd = System.Random()<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L14\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"14\"><\/td>\n          <td id=\"file-forest-fs-LC14\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L15\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"15\"><\/td>\n          <td id=\"file-forest-fs-LC15\" class=\"blob-code blob-code-inner js-file-line\">    let empty : Forest = []<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L16\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"16\"><\/td>\n          <td id=\"file-forest-fs-LC16\" class=\"blob-code blob-code-inner js-file-line\">    <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L17\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"17\"><\/td>\n          <td id=\"file-forest-fs-LC17\" class=\"blob-code blob-code-inner js-file-line\">    // Prune one tree if we&#39;re over the max size<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L18\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"18\"><\/td>\n          <td id=\"file-forest-fs-LC18\" class=\"blob-code blob-code-inner js-file-line\">    let private prune max (forest : Forest) : Forest = <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L19\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"19\"><\/td>\n          <td id=\"file-forest-fs-LC19\" class=\"blob-code blob-code-inner js-file-line\">        let l = List.length forest<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L20\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"20\"><\/td>\n          <td id=\"file-forest-fs-LC20\" class=\"blob-code blob-code-inner js-file-line\">        if max &lt; l then<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L21\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"21\"><\/td>\n          <td id=\"file-forest-fs-LC21\" class=\"blob-code blob-code-inner js-file-line\">            // Remove an &quot;older&quot; tree, from the 2nd half of the list<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L22\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"22\"><\/td>\n          <td id=\"file-forest-fs-LC22\" class=\"blob-code blob-code-inner js-file-line\">            let indexToRemove = rnd.Next ( l / 2, l)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L23\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"23\"><\/td>\n          <td id=\"file-forest-fs-LC23\" class=\"blob-code blob-code-inner js-file-line\">            forest <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L24\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"24\"><\/td>\n          <td id=\"file-forest-fs-LC24\" class=\"blob-code blob-code-inner js-file-line\">            |&gt; List.mapi (fun i t -&gt; (i &lt;&gt; indexToRemove, t))<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L25\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"25\"><\/td>\n          <td id=\"file-forest-fs-LC25\" class=\"blob-code blob-code-inner js-file-line\">            |&gt; List.filter fst<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L26\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"26\"><\/td>\n          <td id=\"file-forest-fs-LC26\" class=\"blob-code blob-code-inner js-file-line\">            |&gt; List.map snd<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L27\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"27\"><\/td>\n          <td id=\"file-forest-fs-LC27\" class=\"blob-code blob-code-inner js-file-line\">        else<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L28\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"28\"><\/td>\n          <td id=\"file-forest-fs-LC28\" class=\"blob-code blob-code-inner js-file-line\">            forest         <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L29\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"29\"><\/td>\n          <td id=\"file-forest-fs-LC29\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L30\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"30\"><\/td>\n          <td id=\"file-forest-fs-LC30\" class=\"blob-code blob-code-inner js-file-line\">    let update msg forest =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L31\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"31\"><\/td>\n          <td id=\"file-forest-fs-LC31\" class=\"blob-code blob-code-inner js-file-line\">        match msg with<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L32\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"32\"><\/td>\n          <td id=\"file-forest-fs-LC32\" class=\"blob-code blob-code-inner js-file-line\">            | Add(location)         -&gt; Tree.create location :: forest    <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L33\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"33\"><\/td>\n          <td id=\"file-forest-fs-LC33\" class=\"blob-code blob-code-inner js-file-line\">            | UpdateTree(msg, tree) -&gt; Tree.update msg tree :: List.except [ tree ] forest<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L34\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"34\"><\/td>\n          <td id=\"file-forest-fs-LC34\" class=\"blob-code blob-code-inner js-file-line\">            | Prune(maxTrees)       -&gt; prune maxTrees forest<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forest-fs-L35\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"35\"><\/td>\n          <td id=\"file-forest-fs-LC35\" class=\"blob-code blob-code-inner js-file-line\">            <\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390/raw/d2a4c06d08d82dda677d941054a7e02e7c3a6236/forest.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390#file-forest-fs\" class=\"Link--inTextBlock\">\n          forest.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>The main differences when compared to the version from last year is thatÂ the logic is now contained in a module, and the message type for updating a forest is dramatically simplified, and now has three options &#8211; it can add a new tree, given a location, prune the existing forest if it&#8217;s larger than a given size, and update a tree given a TreeMessage and a Tree. Â The logic for these just calls into the Tree module when appropriate, making this far easier to understand and extend in the future.</p>
<p>The code up to this point is completely &#8220;pure F#&#8221; &#8211; no external libraries are required, and everything is self contained, testable, immutable, and easy to reason about. Â I have a Forest comprised of a list of TreeÂ records, with functions performing updates that returning a new Forest.</p>
<p>Up to this point, what I have is very similar to what I hadÂ <a href="http://reedcopsey.com/2015/12/09/christmas-trees-in-wpf-using-fsharp-viewmodule/">last year,</a>Â just slightly more organized, with the Tree having its own moduleÂ isolating its own logic.</p>
<p>However, this is where things start to change. Â In order to wire this up to a UI, there areÂ a few options.</p>
<p>I could go with a naive, just &#8220;build out the controls and wire up everything in code&#8221; style. Â This would work, but tends to lead to a mess of spaghetti, lots of brittle event handling for changing the views and pushing back state, and other issues. Â It becomes even more of a mess when considering the fact that the model is represented by a collection &#8211; hand-wiring events for managing collections is difficult to get correct, and typically requires a lot of code.</p>
<p>I could go with a classic MVVM approach: this would likely require making a &#8220;viewÂ model&#8221; class to represent a forest and another to represent tree, adding logic in the tree for whether it should be decorated, and adding some mechanism, typically either custom events or a messaging service, to notify the main view model that a tree is updated, wiring up the logic to map to and from theÂ (immutable) model classes, and the like. Â Realistically, the boilerplate required to do this would be far more code than I&#8217;ve written for the actual application so far &#8211; with the collections becoming the most difficult aspect. Â Libraries like ReactiveUI or DynamicData can simplify this, but it still is effectively copying the model (manually) into aÂ custom collection of view models, managing them, and manually constructing the model back from the results.</p>
<p>My approach last year was to use FSharp.ViewModule&#8217;s EventViewModelBase and custom converters to manage some of this complexity. Â That worked quite well &#8211; and I was happy (mostly) with the approach, but even so, I ended up creating a custom view model class, two MailboxProcessors to manage synchronization, and a lot of care had to be taken to make sure to always marshal back onto the UI thread before touching the collection (or you get exceptions from WPF) and similar &#8220;gotchas&#8221; that really are completely separate concerns from my core logic. Â At its core this approach still uses an MVVM philosophy for its architecture,Â though it has a much more functional slant which does help tame some of the complexity.</p>
<p>MVVM, while the most common architectural pattern for dealing with WPF, has some fundamental flaws. Â At its core, MVVM is about isolating the view and using data binding to wire up changes to a &#8220;view model&#8221;, where the changes edit properties, and then the view model takes on the requirements of updating the model. Â I&#8217;ve written about <a href="http://reedcopsey.com/2010/01/06/better-user-and-developer-experiences-from-windows-forms-to-wpf-with-mvvm-part-7-mvvm/">MVVM in detail</a>, and used it quite a bit, but there are a few annoying aspects:</p>
<ul>
<li>Everything is based on mutation. Â By definition, the View Model layer is going to be mutable, as edits work via (two way) data binding that set values on the properties.</li>
<li>There&#8217;s a lot of boilerplate involved &#8211; every view typically ends up needing a complete class written for it to manage its state and logic.</li>
<li>It can be difficult to reason about, <em>especially</em> when collections are involved.</li>
<li>The &#8220;plumbing&#8221; requirements to keep updates within collections can become onerous quickly. Â This tends to lead to inappropriate changes being made to the Model, as evidenced by the common arguments like &#8220;it&#8217;s just easier if I make this model mutable and implement INotifyPropertyChanged&#8221;. Â Over time, this can make the application far more complex, introduce bugs, and cause a myriad of other problems.</li>
</ul>
<p>That being said, MVVM does bring some concrete benefits:</p>
<ul>
<li>The View stays very isolated, and can be changed without changing the application logic and code <em>at all.</em></li>
<li>The Model can be kept &#8220;pure&#8221;, which allows for easy reuse of the core code in other platforms (though, in practice, this is often broken &#8211; see above).</li>
</ul>
<p>This year, I&#8217;ve decided to go with a completely different approach.</p>
<p>At the beginning of 2016, I started playing with ideas of how to break some of the underlying expectations when building WPF (and other data binding based) applications. Â This centered around a couple of ideas -Â rethinking data binding to eliminate mutation at its core and eliminating the need to create classesÂ to make data binding work. Â This has evolved into the <a href="https://github.com/ReedCopsey/Gjallarhorn">Gjallarhorn.Binding project, built on top of Gjallarhorn</a>.</p>
<p>In order to build aÂ UI with Gjallarhorn, instead of making classes to support data binding, IÂ create some simple functions, referred to as a &#8220;Component&#8221; in Gjallarhorn.Bindable. Â A Component is defined as:</p>
<pre>BindingSource -&gt; ISignal&lt;'TModel&gt; -&gt; IObservable&lt;'TMessage&gt; list</pre>
<p>The BindingSource type is defined in Gjallarhorn.Bindable, and usedÂ to map the model to the view, and events from the view back into messages. Â The ISignal&lt;&#8216;a&gt; interface is the core type in Gjallarhorn, and can be thought of as an IObservable&lt;&#8216;a&gt; (which it inherits) that alwaysÂ contains a current value. Â Gjallarhorn provides a full set of operations for working with signals, including mapping, merging, filtering, conversion to and from observables and other types, and more. Â The Component for mapping the Tree to something usable by data binding is defined as:</p>
<p><style> #wrap_githubgistf18b683b9d8d25056ebf70087c522390 .gist-data {max-height: 100%;} </style><div id="wrap_githubgistf18b683b9d8d25056ebf70087c522390" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist42896112\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-treecomponent-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"treeComponent.fs content, created by ReedCopsey on 01:08AM on December 15, 2016.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"treeComponent.fs\">\n        <tr>\n          <td id=\"file-treecomponent-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-treecomponent-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">// Create binding for a single tree.  This will output Decorate messages<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-treecomponent-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">let treeComponent source (model : ISignal&lt;Tree&gt;) =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-treecomponent-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">    // Bind the tree itself to the view<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-treecomponent-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">    model |&gt; Binding.toView source &quot;Tree&quot;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-treecomponent-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-treecomponent-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">    [<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-treecomponent-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">        // Create a command that turns into the Decorate message<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent-fs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-treecomponent-fs-LC8\" class=\"blob-code blob-code-inner js-file-line\">        source |&gt; Binding.createMessage &quot;Decorate&quot; Decorate <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent-fs-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-treecomponent-fs-LC9\" class=\"blob-code blob-code-inner js-file-line\">    ]<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390/raw/d2a4c06d08d82dda677d941054a7e02e7c3a6236/treeComponent.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390#file-treecomponent-fs\" class=\"Link--inTextBlock\">\n          treeComponent.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>This function takes the model (the ISignal&lt;Tree&gt;) and binds it directly &#8220;to the view&#8221; via the name &#8220;Tree&#8221;. Â This effectively creates a one-way &#8220;Tree property&#8221; the view can data bind into. Â I then create a &#8220;message source&#8221;, which WPF sees as an ICommand. Â The Binding.createMessage function returns an IObservable&lt;&#8216;a&gt;. When the command is executed, it will output a Decorate message into the observable stream.</p>
<p>Similarly, IÂ create a Component to manage the Forest type as a whole:</p>
<p><style> #wrap_githubgistf18b683b9d8d25056ebf70087c522390 .gist-data {max-height: 100%;} </style><div id="wrap_githubgistf18b683b9d8d25056ebf70087c522390" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist42896112\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-forestcomponent-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"forestComponent.fs content, created by ReedCopsey on 01:08AM on December 15, 2016.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"forestComponent.fs\">\n        <tr>\n          <td id=\"file-forestcomponent-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-forestcomponent-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">// Create binding for entire application.  This will output all of our messages.<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forestcomponent-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-forestcomponent-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">let forestComponent source (model : ISignal&lt;Forest&gt;) =             <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forestcomponent-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-forestcomponent-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">    // Bind our collection to &quot;Forest&quot;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forestcomponent-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-forestcomponent-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">    let forest = BindingCollection.toView source &quot;Forest&quot; model treeComponent             <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forestcomponent-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-forestcomponent-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forestcomponent-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-forestcomponent-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">    [<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forestcomponent-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-forestcomponent-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">        // Map Decorate messages in the treeComponent to UpdateTree messages<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forestcomponent-fs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-forestcomponent-fs-LC8\" class=\"blob-code blob-code-inner js-file-line\">        forest |&gt; Observable.map UpdateTree<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forestcomponent-fs-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-forestcomponent-fs-LC9\" class=\"blob-code blob-code-inner js-file-line\">        // Create a command that routes to Add messages<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forestcomponent-fs-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-forestcomponent-fs-LC10\" class=\"blob-code blob-code-inner js-file-line\">        source |&gt; Binding.createMessageParam &quot;Add&quot; Add<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-forestcomponent-fs-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-forestcomponent-fs-LC11\" class=\"blob-code blob-code-inner js-file-line\">    ]<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390/raw/d2a4c06d08d82dda677d941054a7e02e7c3a6236/forestComponent.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390#file-forestcomponent-fs\" class=\"Link--inTextBlock\">\n          forestComponent.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>This is slightly different &#8211; as theÂ Forest is aÂ sequence, I use BindingCollection.toView to bind the entire collection to the view, saying &#8220;for each item in the sequence (a Tree), use the treeComponent function to build out the binding for that element, and aggregate all of the messages from those into a single message stream that&#8217;s the original message and the individual tree as a tuple. Â I then map this in theÂ output stream into UpdateTree message types, and also create a command to add a new tree, which maps the command parameter into the argument of the Add DU case.</p>
<p>Finally, IÂ build the application plumbing. Â The one thing I&#8217;mÂ not handling at this point is pruning of the forest &#8211; which IÂ want to just run continually. Â For Gjallarhorn.Bindable, IÂ need to create three functions for the application &#8211; a function to create theÂ initial model (the Forest), an init function that runs one time after all of the contexts have been setup, and an update function for the top level model. Â These are passed into the Framework.application function, along with the main component, which builds out the &#8220;logical application&#8221;:</p>
<p><style> #wrap_githubgistf18b683b9d8d25056ebf70087c522390 .gist-data {max-height: 100%;} </style><div id="wrap_githubgistf18b683b9d8d25056ebf70087c522390" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist42896112\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-application-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"application.fs content, created by ReedCopsey on 01:08AM on December 15, 2016.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"application.fs\">\n        <tr>\n          <td id=\"file-application-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-application-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">let application = <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-application-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">    // Create our forest, wrapped in a mutable with an atomic update function<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-application-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">    let forest = new AsyncMutable&lt;_&gt;(Forest.empty)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-application-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-application-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">    // Create our 3 functions for the application framework<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-application-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-application-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">    // Start with the function to create our model (as an ISignal&lt;&#39;a&gt;)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-application-fs-LC8\" class=\"blob-code blob-code-inner js-file-line\">    let createModel () : ISignal&lt;_&gt; = forest :&gt; _<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-application-fs-LC9\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-application-fs-LC10\" class=\"blob-code blob-code-inner js-file-line\">    // Create a function that updates our state given a message<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-application-fs-LC11\" class=\"blob-code blob-code-inner js-file-line\">    // Note that we&#39;re just taking the message, passing it directly to our model&#39;s update function,<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L12\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"12\"><\/td>\n          <td id=\"file-application-fs-LC12\" class=\"blob-code blob-code-inner js-file-line\">    // then using that to update our core &quot;Mutable&quot; type.<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L13\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"13\"><\/td>\n          <td id=\"file-application-fs-LC13\" class=\"blob-code blob-code-inner js-file-line\">    let update (msg : ForestMessage) : unit = Forest.update msg |&gt; forest.Update |&gt; ignore<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L14\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"14\"><\/td>\n          <td id=\"file-application-fs-LC14\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L15\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"15\"><\/td>\n          <td id=\"file-application-fs-LC15\" class=\"blob-code blob-code-inner js-file-line\">    // An init function that occurs once everything&#39;s created, but before it starts<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L16\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"16\"><\/td>\n          <td id=\"file-application-fs-LC16\" class=\"blob-code blob-code-inner js-file-line\">    let init () : unit = <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L17\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"17\"><\/td>\n          <td id=\"file-application-fs-LC17\" class=\"blob-code blob-code-inner js-file-line\">        // Handle pruning of the forest - <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L18\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"18\"><\/td>\n          <td id=\"file-application-fs-LC18\" class=\"blob-code blob-code-inner js-file-line\">        // Once per second, send a prune message to remove a tree if there are more than max<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L19\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"19\"><\/td>\n          <td id=\"file-application-fs-LC19\" class=\"blob-code blob-code-inner js-file-line\">        let rec pruneForever max update =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L20\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"20\"><\/td>\n          <td id=\"file-application-fs-LC20\" class=\"blob-code blob-code-inner js-file-line\">            async {<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L21\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"21\"><\/td>\n          <td id=\"file-application-fs-LC21\" class=\"blob-code blob-code-inner js-file-line\">                do! Async.Sleep 500<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L22\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"22\"><\/td>\n          <td id=\"file-application-fs-LC22\" class=\"blob-code blob-code-inner js-file-line\">            <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L23\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"23\"><\/td>\n          <td id=\"file-application-fs-LC23\" class=\"blob-code blob-code-inner js-file-line\">                Prune max |&gt; update<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L24\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"24\"><\/td>\n          <td id=\"file-application-fs-LC24\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L25\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"25\"><\/td>\n          <td id=\"file-application-fs-LC25\" class=\"blob-code blob-code-inner js-file-line\">                do! pruneForever max update<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L26\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"26\"><\/td>\n          <td id=\"file-application-fs-LC26\" class=\"blob-code blob-code-inner js-file-line\">            }<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L27\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"27\"><\/td>\n          <td id=\"file-application-fs-LC27\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L28\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"28\"><\/td>\n          <td id=\"file-application-fs-LC28\" class=\"blob-code blob-code-inner js-file-line\">        // Start prune loop in the background asynchronously<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L29\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"29\"><\/td>\n          <td id=\"file-application-fs-LC29\" class=\"blob-code blob-code-inner js-file-line\">        pruneForever 10 update |&gt; Async.Start <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L30\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"30\"><\/td>\n          <td id=\"file-application-fs-LC30\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L31\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"31\"><\/td>\n          <td id=\"file-application-fs-LC31\" class=\"blob-code blob-code-inner js-file-line\">    // Start our application<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-application-fs-L32\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"32\"><\/td>\n          <td id=\"file-application-fs-LC32\" class=\"blob-code blob-code-inner js-file-line\">    Framework.application createModel init update forestComponent <\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390/raw/d2a4c06d08d82dda677d941054a7e02e7c3a6236/application.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390#file-application-fs\" class=\"Link--inTextBlock\">\n          application.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>At this point, IÂ have the underlying logic forÂ the entire application defined &#8211; and best of all, it&#8217;s defined in a portable class library that&#8217;s completely reusable as-is between WPF and other data binding platformsÂ &#8211; I could use this same project, without changes, to build out a Xamarin Forms Android app, for example.</p>
<p>The WPF project just references this, pulls in FsXaml, and has two files. Â First, IÂ define the XAML for the View:</p>
<p><style> #wrap_githubgistf18b683b9d8d25056ebf70087c522390 .gist-data {max-height: 100%;} </style><div id="wrap_githubgistf18b683b9d8d25056ebf70087c522390" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist42896112\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-mainwindow-xaml\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-xml  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"mainwindow.xaml content, created by ReedCopsey on 01:08AM on December 15, 2016.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"mainwindow.xaml\">\n        <tr>\n          <td id=\"file-mainwindow-xaml-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC1\" class=\"blob-code blob-code-inner js-file-line\">&lt;Window <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC2\" class=\"blob-code blob-code-inner js-file-line\">        xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;        <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC3\" class=\"blob-code blob-code-inner js-file-line\">        xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC4\" class=\"blob-code blob-code-inner js-file-line\">        xmlns:sys=&quot;clr-namespace:System;assembly=mscorlib&quot;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC5\" class=\"blob-code blob-code-inner js-file-line\">        xmlns:fsx=&quot;clr-namespace:FsXaml;assembly=FsXaml.Wpf&quot;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC6\" class=\"blob-code blob-code-inner js-file-line\">        xmlns:fsxb=&quot;clr-namespace:FsXaml;assembly=FsXaml.Wpf.Blend&quot;        <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC7\" class=\"blob-code blob-code-inner js-file-line\">        xmlns:local=&quot;clr-namespace:Views;assembly=AdventTrees2016&quot;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC8\" class=\"blob-code blob-code-inner js-file-line\">        xmlns:i=&quot;clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity&quot; <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC9\" class=\"blob-code blob-code-inner js-file-line\">        Title=&quot;FsAdvent 2016 - Decorate Some Trees!&quot; <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC10\" class=\"blob-code blob-code-inner js-file-line\">        Name=&quot;Win&quot;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC11\" class=\"blob-code blob-code-inner js-file-line\">        Height=&quot;500&quot; <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L12\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"12\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC12\" class=\"blob-code blob-code-inner js-file-line\">        Width=&quot;500&quot;&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L13\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"13\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC13\" class=\"blob-code blob-code-inner js-file-line\">    &lt;Window.Resources&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L14\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"14\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC14\" class=\"blob-code blob-code-inner js-file-line\">        &lt;local:LocationConverter x:Key=&quot;locationConverter&quot; /&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L15\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"15\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC15\" class=\"blob-code blob-code-inner js-file-line\">        &lt;fsx:BooleanToVisibilityConverter x:Key=&quot;boolToVis&quot; /&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L16\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"16\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC16\" class=\"blob-code blob-code-inner js-file-line\">        &lt;DataTemplate x:Key=&quot;TreeTemplate&quot;&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L17\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"17\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC17\" class=\"blob-code blob-code-inner js-file-line\">            &lt;Canvas&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L18\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"18\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC18\" class=\"blob-code blob-code-inner js-file-line\">                &lt;i:Interaction.Triggers&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L19\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"19\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC19\" class=\"blob-code blob-code-inner js-file-line\">                    &lt;i:EventTrigger EventName=&quot;MouseLeftButtonDown&quot;&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L20\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"20\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC20\" class=\"blob-code blob-code-inner js-file-line\">                        &lt;fsxb:EventToCommand Command=&quot;{Binding Decorate}&quot; /&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L21\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"21\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC21\" class=\"blob-code blob-code-inner js-file-line\">                    &lt;/i:EventTrigger&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L22\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"22\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC22\" class=\"blob-code blob-code-inner js-file-line\">                &lt;/i:Interaction.Triggers&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L23\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"23\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC23\" class=\"blob-code blob-code-inner js-file-line\">                &lt;Path DataContext=&quot;{Binding Tree}&quot; Fill=&quot;DarkGreen&quot; Stroke=&quot;DarkGreen&quot; StrokeThickness=&quot;1&quot; Data=&quot;M 0 -50 L -15 40 L -2 40 L -2 50 L 2 50 L 2 40 L 15 40 Z&quot; RenderTransformOrigin=&quot;0.5,0.5&quot; &gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L24\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"24\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC24\" class=\"blob-code blob-code-inner js-file-line\">                    &lt;Path.RenderTransform&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L25\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"25\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC25\" class=\"blob-code blob-code-inner js-file-line\">                        &lt;TransformGroup&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L26\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"26\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC26\" class=\"blob-code blob-code-inner js-file-line\">                            &lt;ScaleTransform ScaleX=&quot;0.15&quot; ScaleY=&quot;0.1&quot; /&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L27\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"27\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC27\" class=\"blob-code blob-code-inner js-file-line\">                            &lt;ScaleTransform ScaleX=&quot;{Binding Height}&quot; ScaleY=&quot;{Binding Height}&quot; /&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L28\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"28\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC28\" class=\"blob-code blob-code-inner js-file-line\">                            &lt;TranslateTransform X=&quot;{Binding Position.X}&quot; Y =&quot;{Binding Position.Y}&quot;/&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L29\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"29\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC29\" class=\"blob-code blob-code-inner js-file-line\">                        &lt;/TransformGroup&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L30\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"30\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC30\" class=\"blob-code blob-code-inner js-file-line\">                    &lt;/Path.RenderTransform&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L31\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"31\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC31\" class=\"blob-code blob-code-inner js-file-line\">                &lt;/Path&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L32\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"32\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC32\" class=\"blob-code blob-code-inner js-file-line\">                &lt;Path DataContext=&quot;{Binding Tree}&quot; Visibility=&quot;{Binding Decorated, Converter={StaticResource boolToVis}}&quot; Fill=&quot;Red&quot; Stroke=&quot;Red&quot; StrokeThickness=&quot;4&quot; Data=&quot;M -6 -30 L 6 -28 M -12 0 L 12 3 M -16 30 L 16 34&quot; RenderTransformOrigin=&quot;0.5,0.5&quot; &gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L33\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"33\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC33\" class=\"blob-code blob-code-inner js-file-line\">                    &lt;Path.RenderTransform&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L34\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"34\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC34\" class=\"blob-code blob-code-inner js-file-line\">                        &lt;TransformGroup&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L35\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"35\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC35\" class=\"blob-code blob-code-inner js-file-line\">                            &lt;ScaleTransform ScaleX=&quot;0.15&quot; ScaleY=&quot;0.1&quot; /&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L36\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"36\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC36\" class=\"blob-code blob-code-inner js-file-line\">                            &lt;ScaleTransform ScaleX=&quot;{Binding Height}&quot; ScaleY=&quot;{Binding Height}&quot; /&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L37\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"37\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC37\" class=\"blob-code blob-code-inner js-file-line\">                            &lt;TranslateTransform X=&quot;{Binding Position.X}&quot; Y =&quot;{Binding Position.Y}&quot;/&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L38\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"38\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC38\" class=\"blob-code blob-code-inner js-file-line\">                        &lt;/TransformGroup&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L39\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"39\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC39\" class=\"blob-code blob-code-inner js-file-line\">                    &lt;/Path.RenderTransform&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L40\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"40\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC40\" class=\"blob-code blob-code-inner js-file-line\">                &lt;/Path&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L41\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"41\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC41\" class=\"blob-code blob-code-inner js-file-line\">            &lt;/Canvas&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L42\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"42\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC42\" class=\"blob-code blob-code-inner js-file-line\">        &lt;/DataTemplate&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L43\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"43\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC43\" class=\"blob-code blob-code-inner js-file-line\">    &lt;/Window.Resources&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L44\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"44\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC44\" class=\"blob-code blob-code-inner js-file-line\">    &lt;Grid&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L45\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"45\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC45\" class=\"blob-code blob-code-inner js-file-line\">        &lt;Grid.RowDefinitions&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L46\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"46\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC46\" class=\"blob-code blob-code-inner js-file-line\">            &lt;RowDefinition Height=&quot;Auto&quot; /&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L47\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"47\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC47\" class=\"blob-code blob-code-inner js-file-line\">            &lt;RowDefinition Height=&quot;*&quot;/&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L48\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"48\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC48\" class=\"blob-code blob-code-inner js-file-line\">        &lt;/Grid.RowDefinitions&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L49\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"49\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC49\" class=\"blob-code blob-code-inner js-file-line\">        &lt;TextBlock HorizontalAlignment=&quot;Center&quot;&gt;Click to add a Tree - Click on a tree to decorate it.&lt;/TextBlock&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L50\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"50\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC50\" class=\"blob-code blob-code-inner js-file-line\">        &lt;ItemsControl <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L51\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"51\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC51\" class=\"blob-code blob-code-inner js-file-line\">            Grid.Row=&quot;1&quot; HorizontalAlignment=&quot;Stretch&quot; VerticalAlignment=&quot;Stretch&quot; <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L52\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"52\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC52\" class=\"blob-code blob-code-inner js-file-line\">            ItemsSource=&quot;{Binding Forest}&quot; <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L53\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"53\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC53\" class=\"blob-code blob-code-inner js-file-line\">            ItemTemplate=&quot;{StaticResource TreeTemplate}&quot;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L54\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"54\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC54\" class=\"blob-code blob-code-inner js-file-line\">            &gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L55\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"55\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC55\" class=\"blob-code blob-code-inner js-file-line\">            &lt;ItemsControl.ItemsPanel&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L56\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"56\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC56\" class=\"blob-code blob-code-inner js-file-line\">                &lt;ItemsPanelTemplate&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L57\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"57\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC57\" class=\"blob-code blob-code-inner js-file-line\">                    &lt;Canvas HorizontalAlignment=&quot;Stretch&quot; VerticalAlignment=&quot;Stretch&quot; Background=&quot;Gray&quot; ClipToBounds=&quot;True&quot; &gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L58\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"58\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC58\" class=\"blob-code blob-code-inner js-file-line\">                        &lt;i:Interaction.Triggers&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L59\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"59\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC59\" class=\"blob-code blob-code-inner js-file-line\">                            &lt;i:EventTrigger EventName=&quot;MouseLeftButtonDown&quot;&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L60\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"60\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC60\" class=\"blob-code blob-code-inner js-file-line\">                                &lt;fsxb:EventToCommand Command=&quot;{Binding Add}&quot; FilterOptionEventArgs=&quot;True&quot; EventArgsConverter=&quot;{StaticResource locationConverter}&quot;  /&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L61\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"61\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC61\" class=\"blob-code blob-code-inner js-file-line\">                            &lt;/i:EventTrigger&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L62\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"62\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC62\" class=\"blob-code blob-code-inner js-file-line\">                        &lt;/i:Interaction.Triggers&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L63\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"63\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC63\" class=\"blob-code blob-code-inner js-file-line\">                    &lt;/Canvas&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L64\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"64\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC64\" class=\"blob-code blob-code-inner js-file-line\">                &lt;/ItemsPanelTemplate&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L65\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"65\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC65\" class=\"blob-code blob-code-inner js-file-line\">            &lt;/ItemsControl.ItemsPanel&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L66\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"66\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC66\" class=\"blob-code blob-code-inner js-file-line\">        &lt;/ItemsControl&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L67\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"67\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC67\" class=\"blob-code blob-code-inner js-file-line\">    &lt;/Grid&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-mainwindow-xaml-L68\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"68\"><\/td>\n          <td id=\"file-mainwindow-xaml-LC68\" class=\"blob-code blob-code-inner js-file-line\">&lt;/Window&gt;<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390/raw/d2a4c06d08d82dda677d941054a7e02e7c3a6236/mainwindow.xaml\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390#file-mainwindow-xaml\" class=\"Link--inTextBlock\">\n          mainwindow.xaml\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>This looks very similar to the XAML fromÂ last year, except that I moved the Tree rendering into its own resource, and simplified the event handling. Â I no longer need two converters &#8211; only a single converter is required (to go from clicking on the Canvas to a Location for adding a tree) &#8211; Gjallarhorn.Bindable takes care of mapping the ICommand to aÂ Decorate message without any work being done in the View, but clicking on the Canvas and mapping to a location requires a converter to be written:</p>
<p><style> #wrap_githubgistf18b683b9d8d25056ebf70087c522390 .gist-data {max-height: 100%;} </style><div id="wrap_githubgistf18b683b9d8d25056ebf70087c522390" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist42896112\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-view1-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"view1.fs content, created by ReedCopsey on 01:08AM on December 15, 2016.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"view1.fs\">\n        <tr>\n          <td id=\"file-view1-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-view1-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">module internal MouseConverters =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view1-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-view1-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">    // Create a converter from mouse clicks on a Canvas to Some(location), and clicks elsewhere to None<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view1-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-view1-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">    let locationConverter (args : MouseEventArgs) =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view1-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-view1-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">        match args.OriginalSource with<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view1-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-view1-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">        | :? Canvas -&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view1-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-view1-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">            let source = args.OriginalSource :?&gt; IInputElement<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view1-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-view1-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">            let pt = args.GetPosition(source)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view1-fs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-view1-fs-LC8\" class=\"blob-code blob-code-inner js-file-line\">            Some { X = pt.X; Y = pt.Y }<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view1-fs-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-view1-fs-LC9\" class=\"blob-code blob-code-inner js-file-line\">        | _ -&gt; None<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view1-fs-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-view1-fs-LC10\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view1-fs-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-view1-fs-LC11\" class=\"blob-code blob-code-inner js-file-line\">// Create our converter from MouseEventArgs -&gt; Location<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view1-fs-L12\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"12\"><\/td>\n          <td id=\"file-view1-fs-LC12\" class=\"blob-code blob-code-inner js-file-line\">type LocationConverter() = inherit EventArgsConverter&lt;MouseEventArgs, Location option&gt;(MouseConverters.locationConverter, None)<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390/raw/d2a4c06d08d82dda677d941054a7e02e7c3a6236/view1.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390#file-view1-fs\" class=\"Link--inTextBlock\">\n          view1.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>This converter is similar to the one last year &#8211; but I&#8217;mÂ taking advantage of a newer FsXaml feature that allows us toÂ convert to an option and filter out None results automatically.</p>
<p>Once that&#8217;s done, IÂ load theÂ XAML using the FsXaml type provider, and the application entry point becomes nothing but having the WPF specific portion of Gjallarhorn (from the Gjallarhorn.Bindable.Wpf reference) launch the application. Â This just requires a singleÂ function call &#8211; it takes a function to construct an Application (in this case, I&#8217;m using the default WPF application), the main Window (from the type provider), and the application from the portable class library:</p>
<p><style> #wrap_githubgistf18b683b9d8d25056ebf70087c522390 .gist-data {max-height: 100%;} </style><div id="wrap_githubgistf18b683b9d8d25056ebf70087c522390" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist42896112\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-view2-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"view2.fs content, created by ReedCopsey on 01:08AM on December 15, 2016.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"view2.fs\">\n        <tr>\n          <td id=\"file-view2-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-view2-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">// Create our Window<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view2-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-view2-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">type MainWindow = XAML&lt;&quot;MainWindow.xaml&quot;&gt; <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view2-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-view2-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view2-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-view2-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">module Main =    <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view2-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-view2-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">    [&lt;STAThread&gt;]<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view2-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-view2-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">    [&lt;EntryPoint&gt;]<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view2-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-view2-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">    let main _ =  <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view2-fs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-view2-fs-LC8\" class=\"blob-code blob-code-inner js-file-line\">        // Run using the WPF wrappers around the basic application framework    <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view2-fs-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-view2-fs-LC9\" class=\"blob-code blob-code-inner js-file-line\">        Gjallarhorn.Wpf.Framework.runApplication System.Windows.Application MainWindow Program.application<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390/raw/d2a4c06d08d82dda677d941054a7e02e7c3a6236/view2.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390#file-view2-fs\" class=\"Link--inTextBlock\">\n          view2.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>That&#8217;s it &#8211; the entire application. Â Every line of source code (other than namespace definitions and open statements) is included. Â When I run, I get an improved version of what IÂ had last year. Â I can click on the window to add trees, and click on a tree to decorate them. Â The main improvement isÂ in the pruning behavior &#8211; if IÂ add more than 10 trees, I start to seeÂ some disappear one at a time every half second, using someÂ randomness that didn&#8217;t exist in the previous version.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-373" src="http://reedcopsey.com/blog/wp-content/uploads/2016/12/Advent2016_1.png" alt="" width="486" height="493" srcset="http://reedcopsey.com/blog/wp-content/uploads/2016/12/Advent2016_1.png 486w, http://reedcopsey.com/blog/wp-content/uploads/2016/12/Advent2016_1-296x300.png 296w" sizes="(max-width: 486px) 100vw, 486px" /></p>
<p>I&#8217;d like to point out some differences here when compared to last year &#8211; The model is completely immutable and pure. Â The entire application state is defined in one place, and easily managed. Â I just need to provide a mechanism to turn it into a signal (to monitor changes) and to update. Â Nowhere in this application do I worry about threading or synchronization, even though the pruning is happening in background threads asynchronously. Â I don&#8217;t create a single &#8220;view model&#8221; class for data binding, rather just define simple functions that map from my model to binding targets, and route messagesÂ out. Â The entire application is simple, easy to reason about, and very clean.</p>
<p>In addition, this application is far easier to modify as requirements change. Â For fun, I&#8217;m going to add some new functionality. Â In addition to decorating the tree, I&#8217;m going to add the ability to light a tree.</p>
<p>I&#8217;ll modify theÂ Model to allow trees to be decorated and lit. This requires changing theÂ Tree record, adding a new Light message, and modifying the update function:</p>
<p><style> #wrap_githubgistf18b683b9d8d25056ebf70087c522390 .gist-data {max-height: 100%;} </style><div id="wrap_githubgistf18b683b9d8d25056ebf70087c522390" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist42896112\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-tree2-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"tree2.fs content, created by ReedCopsey on 01:08AM on December 15, 2016.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"tree2.fs\">\n        <tr>\n          <td id=\"file-tree2-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-tree2-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">// Add &quot;Lit&quot;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree2-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-tree2-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">type Tree = { Position : Location ; Height : float ; Decorated : bool ; Lit : bool }<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree2-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-tree2-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree2-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-tree2-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">// Add Light message<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree2-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-tree2-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">type TreeMessage = | Decorate | Light<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree2-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-tree2-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree2-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-tree2-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">// In module Tree <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree2-fs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-tree2-fs-LC8\" class=\"blob-code blob-code-inner js-file-line\">    // Handle new message here<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree2-fs-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-tree2-fs-LC9\" class=\"blob-code blob-code-inner js-file-line\">    let update msg tree =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree2-fs-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-tree2-fs-LC10\" class=\"blob-code blob-code-inner js-file-line\">        match msg with<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree2-fs-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-tree2-fs-LC11\" class=\"blob-code blob-code-inner js-file-line\">        | Decorate -&gt; { tree with Decorated = true }<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-tree2-fs-L12\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"12\"><\/td>\n          <td id=\"file-tree2-fs-LC12\" class=\"blob-code blob-code-inner js-file-line\">        | Light -&gt; { tree with Lit = true }<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390/raw/d2a4c06d08d82dda677d941054a7e02e7c3a6236/tree2.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390#file-tree2-fs\" class=\"Link--inTextBlock\">\n          tree2.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>Now IÂ need to add another command to theÂ tree component which generates Light messages:</p>
<p><style> #wrap_githubgistf18b683b9d8d25056ebf70087c522390 .gist-data {max-height: 100%;} </style><div id="wrap_githubgistf18b683b9d8d25056ebf70087c522390" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist42896112\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-treecomponent2-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"treeComponent2.fs content, created by ReedCopsey on 01:08AM on December 15, 2016.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"treeComponent2.fs\">\n        <tr>\n          <td id=\"file-treecomponent2-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-treecomponent2-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">let treeComponent source (model : ISignal&lt;Tree&gt;) =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent2-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-treecomponent2-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">    model |&gt; Binding.toView source &quot;Tree&quot;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent2-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-treecomponent2-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent2-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-treecomponent2-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">    [        <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent2-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-treecomponent2-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">        source |&gt; Binding.createMessage &quot;Decorate&quot; Decorate <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent2-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-treecomponent2-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">        // Add one line here to add a new command that maps to the light message<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent2-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-treecomponent2-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">        source |&gt; Binding.createMessage &quot;Light&quot; Light<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-treecomponent2-fs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-treecomponent2-fs-LC8\" class=\"blob-code blob-code-inner js-file-line\">    ]<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390/raw/d2a4c06d08d82dda677d941054a7e02e7c3a6236/treeComponent2.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390#file-treecomponent2-fs\" class=\"Link--inTextBlock\">\n          treeComponent2.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>Finally, I need to tweak the XAML slightly. Â It needs two changes &#8211; a way to trigger the new command (I&#8217;ll use right mouse to light the tree), and the actual rendering of the lights as another path. Â First, IÂ put in the right mouse click EventToCommand:</p>
<p><style> #wrap_githubgistf18b683b9d8d25056ebf70087c522390 .gist-data {max-height: 100%;} </style><div id="wrap_githubgistf18b683b9d8d25056ebf70087c522390" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist42896112\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-rightmouse-xaml\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-xml  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"rightMouse.xaml content, created by ReedCopsey on 01:08AM on December 15, 2016.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"rightMouse.xaml\">\n        <tr>\n          <td id=\"file-rightmouse-xaml-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-rightmouse-xaml-LC1\" class=\"blob-code blob-code-inner js-file-line\">&lt;i:EventTrigger EventName=&quot;MouseRightButtonDown&quot;&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-rightmouse-xaml-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-rightmouse-xaml-LC2\" class=\"blob-code blob-code-inner js-file-line\">    &lt;fsxb:EventToCommand Command=&quot;{Binding Light}&quot; /&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-rightmouse-xaml-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-rightmouse-xaml-LC3\" class=\"blob-code blob-code-inner js-file-line\">&lt;/i:EventTrigger&gt;<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390/raw/d2a4c06d08d82dda677d941054a7e02e7c3a6236/rightMouse.xaml\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390#file-rightmouse-xaml\" class=\"Link--inTextBlock\">\n          rightMouse.xaml\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>And then IÂ add a new path for the lights (full xaml not shown), and update the instructions:</p>
<p><style> #wrap_githubgistf18b683b9d8d25056ebf70087c522390 .gist-data {max-height: 100%;} </style><div id="wrap_githubgistf18b683b9d8d25056ebf70087c522390" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist42896112\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-lightpath-xaml\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-xml  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"lightPath.xaml content, created by ReedCopsey on 01:08AM on December 15, 2016.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"lightPath.xaml\">\n        <tr>\n          <td id=\"file-lightpath-xaml-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-lightpath-xaml-LC1\" class=\"blob-code blob-code-inner js-file-line\">&lt;Path Canvas.ZIndex=&quot;2&quot; DataContext=&quot;{Binding Tree}&quot; Visibility=&quot;{Binding Lit, Converter={StaticResource boolToVis}}&quot; Fill=&quot;White&quot; Stroke=&quot;White&quot; StrokeThickness=&quot;2&quot;<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390/raw/d2a4c06d08d82dda677d941054a7e02e7c3a6236/lightPath.xaml\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/f18b683b9d8d25056ebf70087c522390#file-lightpath-xaml\" class=\"Link--inTextBlock\">\n          lightPath.xaml\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>Now, whenÂ I run, I can light and decorate the trees!</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-374" src="http://reedcopsey.com/blog/wp-content/uploads/2016/12/Advent2016_2.png" alt="" width="486" height="493" srcset="http://reedcopsey.com/blog/wp-content/uploads/2016/12/Advent2016_2.png 486w, http://reedcopsey.com/blog/wp-content/uploads/2016/12/Advent2016_2-296x300.png 296w" sizes="(max-width: 486px) 100vw, 486px" /></p>
<p>This required no major changes to plumbing &#8211; I wanted to update how trees work, so a simple addition to the Tree model, and a couple of lines of code, and I&#8217;m done. Â The <a href="https://github.com/ReedCopsey/AdventTrees2016/commit/5233549e14980f7706162969337ec99bd010779c">entire set of changes required to add lighting is trivial, and can be seen in this GitHub commit</a>.</p>
<p>As always, I&#8217;ve put the <a href="https://github.com/ReedCopsey/AdventTrees2016">code on GitHub</a>, so pleaseÂ download, try it out, andÂ enjoy!</p>
<p>And remember to enjoy the rest of theÂ F#Â content inÂ the 2016 <a href="https://sergeytihon.wordpress.com/tag/fsadvent/">F# Advent Calendar</a>!</p>
<p>&nbsp;</p>
<hr />
<p>Update on Dec 16th: A new <a href="https://github.com/ReedCopsey/AdventTrees2016/tree/blinking">&#8220;blinking&#8221; branch</a> of the repository has been created, showing off submitted improvements, such as making the lights blink on and off! Â Definitely worth trying the original and the improved versions. Â Thank you GeneÂ ChiaramonteÂ (<a href="https://twitter.com/waahhoo">@waahhoo</a>) and family!</p>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2016/12/15/christmas-trees-in-wpf-2016-edition/feed/</wfw:commentRss>
			<slash:comments>8</slash:comments>
		
		
			</item>
		<item>
		<title>Christmas Trees in WPF using FSharp.ViewModule</title>
		<link>http://reedcopsey.com/2015/12/09/christmas-trees-in-wpf-using-fsharp-viewmodule/</link>
					<comments>http://reedcopsey.com/2015/12/09/christmas-trees-in-wpf-using-fsharp-viewmodule/#comments</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Wed, 09 Dec 2015 20:24:23 +0000</pubDate>
				<category><![CDATA[Async]]></category>
		<category><![CDATA[F#]]></category>
		<category><![CDATA[MVVM]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[WPF]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/?p=349</guid>

					<description><![CDATA[As my contribution to the F# Advent Calendar this year, I thought Iâ€™d write a bit about one approach I often use to create WPF user interfaces in a functional style &#8211; mixing MailboxProcessor with FSharp.ViewModule. This post will illustrate using a pair of MailboxProcessor instances mixed with FSharp.ViewModuleÂ toÂ construct a simple application. Â In the spirit [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>As my contribution to the <a href="https://sergeytihon.wordpress.com/tag/fsadvent/">F# Advent Calendar</a> this year, I thought Iâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />d write a bit about one approach I often use to create WPF user interfaces in a functional style &#8211; mixing MailboxProcessor with <a href="https://github.com/fsprojects/FSharp.ViewModule/">FSharp.ViewModule</a>.</p>
<p>This post will illustrate using a pair of MailboxProcessor instances mixed with FSharp.ViewModuleÂ toÂ construct a simple application. Â In the spirit of F# Advent, our application will be a small drawing application that allows us to place and decorate Christmas trees.</p>
<p><span id="more-349"></span></p>
<p>In order to start, we need a way to represent a collection of trees.Â  For this application, Iâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />ve created a simple model, comprised of Tree and Forest records, with some functions for manipulating a Forest:</p>
<p><style> #wrap_githubgistfdc403c3234553c6e52d .gist-data {max-height: 100%;} </style><div id="wrap_githubgistfdc403c3234553c6e52d" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist28781451\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-model-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"Model.fs content, created by ReedCopsey on 08:19PM on December 09, 2015.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"Model.fs\">\n        <tr>\n          <td id=\"file-model-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-model-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">type Location = { X: float; Y: float }<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-model-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-model-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-model-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-model-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">type Tree = { Position : Location ; Height : float ; Decorated : bool }<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-model-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-model-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-model-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-model-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">type Forest = { Trees : Tree list }<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-model-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-model-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">with<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-model-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-model-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">    static member Empty with get() = { Trees = [] }<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-model-fs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-model-fs-LC8\" class=\"blob-code blob-code-inner js-file-line\">    member f.Add tree = <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-model-fs-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-model-fs-LC9\" class=\"blob-code blob-code-inner js-file-line\">        { Trees = tree :: f.Trees }<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-model-fs-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-model-fs-LC10\" class=\"blob-code blob-code-inner js-file-line\">    member f.Decorate tree = <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-model-fs-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-model-fs-LC11\" class=\"blob-code blob-code-inner js-file-line\">        let existing = f.Trees<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-model-fs-L12\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"12\"><\/td>\n          <td id=\"file-model-fs-LC12\" class=\"blob-code blob-code-inner js-file-line\">        let updated = <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-model-fs-L13\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"13\"><\/td>\n          <td id=\"file-model-fs-LC13\" class=\"blob-code blob-code-inner js-file-line\">            existing<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-model-fs-L14\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"14\"><\/td>\n          <td id=\"file-model-fs-LC14\" class=\"blob-code blob-code-inner js-file-line\">            |&gt; List.except [ tree ]<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-model-fs-L15\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"15\"><\/td>\n          <td id=\"file-model-fs-LC15\" class=\"blob-code blob-code-inner js-file-line\">        { Trees = { tree with Decorated = true } :: updated }<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-model-fs-L16\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"16\"><\/td>\n          <td id=\"file-model-fs-LC16\" class=\"blob-code blob-code-inner js-file-line\">    member f.Prune max = <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-model-fs-L17\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"17\"><\/td>\n          <td id=\"file-model-fs-LC17\" class=\"blob-code blob-code-inner js-file-line\">        let updated = <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-model-fs-L18\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"18\"><\/td>\n          <td id=\"file-model-fs-LC18\" class=\"blob-code blob-code-inner js-file-line\">            if max &lt; List.length f.Trees then<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-model-fs-L19\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"19\"><\/td>\n          <td id=\"file-model-fs-LC19\" class=\"blob-code blob-code-inner js-file-line\">                f.Trees<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-model-fs-L20\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"20\"><\/td>\n          <td id=\"file-model-fs-LC20\" class=\"blob-code blob-code-inner js-file-line\">                |&gt; List.take max<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-model-fs-L21\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"21\"><\/td>\n          <td id=\"file-model-fs-LC21\" class=\"blob-code blob-code-inner js-file-line\">            else<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-model-fs-L22\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"22\"><\/td>\n          <td id=\"file-model-fs-LC22\" class=\"blob-code blob-code-inner js-file-line\">                f.Trees<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-model-fs-L23\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"23\"><\/td>\n          <td id=\"file-model-fs-LC23\" class=\"blob-code blob-code-inner js-file-line\">        { Trees = updated }<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/fdc403c3234553c6e52d/raw/7ceaebc3e6301b8b1156da0a9cdbd46cfac5810c/Model.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/fdc403c3234553c6e52d#file-model-fs\" class=\"Link--inTextBlock\">\n          Model.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>In addition, I have a ForestManager module, whichÂ provides a mechanism to use MailboxProcessor to provide updates to a Forest. Â Discriminated unions provide the mechanisms forÂ specifyingÂ an update and receiving a result. Â In our case, an update can beÂ adding a new tree to a forest, or decorating an existing tree within a forest. Â As the entire Forest is immutable, either of these would need to create a new Forest.</p>
<p>In order to request updates, as well as update our view, I&#8217;m using two MailboxProcessors. Â Our view creates a MailboxProcessor&lt;ForestUpdateResult&gt;, which is will use to receive notifications of new Forests. Â The ForestManager has a single function which accepts this processor, and createsÂ a secondary one which can be used to post updates. Â A single processor would work using PostAndReply, but the advantage of having two is that the model can request updates independently of the view layers, and all user events that require an update just post to a MailboxProcessor, whichÂ simplifies the viewÂ dramatically.</p>
<p>The manager effectively just delegates the update requests to the Forest functions, and posts to the view&#8217;s Mailbox whenever an update needs to occur:</p>
<p><style> #wrap_githubgistfdc403c3234553c6e52d .gist-data {max-height: 100%;} </style><div id="wrap_githubgistfdc403c3234553c6e52d" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist28781451\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-manager-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"Manager.fs content, created by ReedCopsey on 08:19PM on December 09, 2015.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"Manager.fs\">\n        <tr>\n          <td id=\"file-manager-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-manager-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">type ForestUpdate =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-manager-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">    | Add of Tree * Forest<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-manager-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">    | Decorate of Tree * Forest<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-manager-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-manager-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">type ForestUpdateResult =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-manager-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">    | Success of Forest<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-manager-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">    | Pruned of Forest<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-manager-fs-LC8\" class=\"blob-code blob-code-inner js-file-line\">    | Error of string<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-manager-fs-LC9\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-manager-fs-LC10\" class=\"blob-code blob-code-inner js-file-line\">module ForestManager =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-manager-fs-LC11\" class=\"blob-code blob-code-inner js-file-line\">    let private update forest f (reporter : MailboxProcessor&lt;ForestUpdateResult&gt;) =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L12\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"12\"><\/td>\n          <td id=\"file-manager-fs-LC12\" class=\"blob-code blob-code-inner js-file-line\">        let updated = f forest<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L13\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"13\"><\/td>\n          <td id=\"file-manager-fs-LC13\" class=\"blob-code blob-code-inner js-file-line\">        Success updated |&gt; reporter.Post<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L14\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"14\"><\/td>\n          <td id=\"file-manager-fs-LC14\" class=\"blob-code blob-code-inner js-file-line\">        if List.length updated.Trees &gt; 10 then<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L15\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"15\"><\/td>\n          <td id=\"file-manager-fs-LC15\" class=\"blob-code blob-code-inner js-file-line\">            updated.Prune 5 |&gt; Pruned |&gt; reporter.Post<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L16\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"16\"><\/td>\n          <td id=\"file-manager-fs-LC16\" class=\"blob-code blob-code-inner js-file-line\">    let createUpdateAgent reporter =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L17\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"17\"><\/td>\n          <td id=\"file-manager-fs-LC17\" class=\"blob-code blob-code-inner js-file-line\">        let updater (inbox : MailboxProcessor&lt;ForestUpdate&gt;) =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L18\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"18\"><\/td>\n          <td id=\"file-manager-fs-LC18\" class=\"blob-code blob-code-inner js-file-line\">            let rec loop() =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L19\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"19\"><\/td>\n          <td id=\"file-manager-fs-LC19\" class=\"blob-code blob-code-inner js-file-line\">                async {<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L20\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"20\"><\/td>\n          <td id=\"file-manager-fs-LC20\" class=\"blob-code blob-code-inner js-file-line\">                    let! forestUpdate = inbox.Receive()<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L21\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"21\"><\/td>\n          <td id=\"file-manager-fs-LC21\" class=\"blob-code blob-code-inner js-file-line\">                    let f, forest = <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L22\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"22\"><\/td>\n          <td id=\"file-manager-fs-LC22\" class=\"blob-code blob-code-inner js-file-line\">                        match forestUpdate with<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L23\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"23\"><\/td>\n          <td id=\"file-manager-fs-LC23\" class=\"blob-code blob-code-inner js-file-line\">                        | Add(tree, forest) -&gt; (fun _ -&gt; forest.Add tree), forest<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L24\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"24\"><\/td>\n          <td id=\"file-manager-fs-LC24\" class=\"blob-code blob-code-inner js-file-line\">                        | Decorate(tree, forest) -&gt; (fun _ -&gt; forest.Decorate tree), forest<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L25\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"25\"><\/td>\n          <td id=\"file-manager-fs-LC25\" class=\"blob-code blob-code-inner js-file-line\">                    update forest f reporter<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L26\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"26\"><\/td>\n          <td id=\"file-manager-fs-LC26\" class=\"blob-code blob-code-inner js-file-line\">                    do! loop()<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L27\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"27\"><\/td>\n          <td id=\"file-manager-fs-LC27\" class=\"blob-code blob-code-inner js-file-line\">                }<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L28\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"28\"><\/td>\n          <td id=\"file-manager-fs-LC28\" class=\"blob-code blob-code-inner js-file-line\">            loop()<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L29\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"29\"><\/td>\n          <td id=\"file-manager-fs-LC29\" class=\"blob-code blob-code-inner js-file-line\">        let result = new MailboxProcessor&lt;ForestUpdate&gt;(updater)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L30\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"30\"><\/td>\n          <td id=\"file-manager-fs-LC30\" class=\"blob-code blob-code-inner js-file-line\">        result.Start()<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-manager-fs-L31\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"31\"><\/td>\n          <td id=\"file-manager-fs-LC31\" class=\"blob-code blob-code-inner js-file-line\">        result<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/fdc403c3234553c6e52d/raw/7ceaebc3e6301b8b1156da0a9cdbd46cfac5810c/Manager.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/fdc403c3234553c6e52d#file-manager-fs\" class=\"Link--inTextBlock\">\n          Manager.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>While this is simple, in a more complicated application, the &#8220;manager&#8221; within the Model layer can very easily add more updates triggered by external sources, which providesÂ oneÂ advantage of having separate MailboxProcessors instead of using a single processorÂ via PostAndReply.</p>
<p>Now that we have our Model layer defined, we need a way to interact with this from the View. Â This is where <a href="https://github.com/fsprojects/FSharp.ViewModule/">FSharp.ViewModule</a>Â comes into play. Â For this application, my view model uses EventViewModelBaseÂ from FSharp.ViewModule. This allows us to react to user input as a stream of strongly typed events.</p>
<p>The first thing we&#8217;ll need is to create our ViewModel and view Event types, and define a single property and backing field for the Forest we&#8217;re viewing.</p>
<p><style> #wrap_githubgistfdc403c3234553c6e52d .gist-data {max-height: 100%;} </style><div id="wrap_githubgistfdc403c3234553c6e52d" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist28781451\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-vm1-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"vm1.fs content, created by ReedCopsey on 08:19PM on December 09, 2015.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"vm1.fs\">\n        <tr>\n          <td id=\"file-vm1-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-vm1-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">type TreeEvent =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm1-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-vm1-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">    | Add of location:Location<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm1-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-vm1-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">    | Decorate of tree:Tree<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm1-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-vm1-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">    | Unknown<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm1-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-vm1-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm1-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-vm1-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">type ForestViewModel () as self =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm1-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-vm1-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">    inherit EventViewModelBase&lt;TreeEvent&gt;()<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm1-fs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-vm1-fs-LC8\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm1-fs-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-vm1-fs-LC9\" class=\"blob-code blob-code-inner js-file-line\">    // Create a backing field for our Forest using FSharp.ViewModule<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm1-fs-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-vm1-fs-LC10\" class=\"blob-code blob-code-inner js-file-line\">    let forest = self.Factory.Backing(&lt;@ self.Forest @&gt;, Forest.Empty)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm1-fs-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-vm1-fs-LC11\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm1-fs-L12\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"12\"><\/td>\n          <td id=\"file-vm1-fs-LC12\" class=\"blob-code blob-code-inner js-file-line\">    // ... Other code...<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm1-fs-L13\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"13\"><\/td>\n          <td id=\"file-vm1-fs-LC13\" class=\"blob-code blob-code-inner js-file-line\">    member __.Forest with get() = forest.Value<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/fdc403c3234553c6e52d/raw/7ceaebc3e6301b8b1156da0a9cdbd46cfac5810c/vm1.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/fdc403c3234553c6e52d#file-vm1-fs\" class=\"Link--inTextBlock\">\n          vm1.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>This allowsÂ the current Forest, defaulting to an empty forest, to be bound by our view. Â All of the INotifyPropertyChanged plumbing gets handled internally by FSharp.ViewModule&#8217;s base classes for us.</p>
<p>Next, we needÂ to create our MailboxProcessors. Â First, we need one that we can listen to in order to receive updates to our Forest. Â Once that&#8217;s created, we can request one to post updates to from the ForestManager module. Â Note that I&#8217;m capturing the SynchronizationContext and handling it within the agent &#8211; in this case, that&#8217;s actually unnecessary, but it makes the updates fully threadsafe with WPF if our Model were to post updates from multiple threads, even if we decided to change how we work with the Forest (such as keeping an ObservableCollection for history, which would require synchronization).</p>
<p><style> #wrap_githubgistfdc403c3234553c6e52d .gist-data {max-height: 100%;} </style><div id="wrap_githubgistfdc403c3234553c6e52d" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist28781451\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-vm2-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"vm2.fs content, created by ReedCopsey on 08:19PM on December 09, 2015.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"vm2.fs\">\n        <tr>\n          <td id=\"file-vm2-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-vm2-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">    let ui = SynchronizationContext.Current<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-vm2-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">    <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-vm2-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">    // Create an async update loop for our agent<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-vm2-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">    let update (inbox : MailboxProcessor&lt;ForestUpdateResult&gt;) =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-vm2-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">        let rec loop() =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-vm2-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">            async {<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-vm2-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">                let! update = inbox.Receive()<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-vm2-fs-LC8\" class=\"blob-code blob-code-inner js-file-line\">                match update with<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-vm2-fs-LC9\" class=\"blob-code blob-code-inner js-file-line\">                | Success updated -&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-vm2-fs-LC10\" class=\"blob-code blob-code-inner js-file-line\">                    do! Async.SwitchToContext ui<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-vm2-fs-LC11\" class=\"blob-code blob-code-inner js-file-line\">                    forest.Value &lt;- updated<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L12\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"12\"><\/td>\n          <td id=\"file-vm2-fs-LC12\" class=\"blob-code blob-code-inner js-file-line\">                | Pruned updated -&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L13\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"13\"><\/td>\n          <td id=\"file-vm2-fs-LC13\" class=\"blob-code blob-code-inner js-file-line\">                    // Wait brief period (so you see the tree added before pruning), then update us<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L14\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"14\"><\/td>\n          <td id=\"file-vm2-fs-LC14\" class=\"blob-code blob-code-inner js-file-line\">                    // Note: This creates a race condition if you click very fast<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L15\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"15\"><\/td>\n          <td id=\"file-vm2-fs-LC15\" class=\"blob-code blob-code-inner js-file-line\">                    do! Async.Sleep 250<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L16\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"16\"><\/td>\n          <td id=\"file-vm2-fs-LC16\" class=\"blob-code blob-code-inner js-file-line\">                    do! Async.SwitchToContext ui<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L17\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"17\"><\/td>\n          <td id=\"file-vm2-fs-LC17\" class=\"blob-code blob-code-inner js-file-line\">                    forest.Value &lt;- updated<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L18\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"18\"><\/td>\n          <td id=\"file-vm2-fs-LC18\" class=\"blob-code blob-code-inner js-file-line\">                | Error _ -&gt; <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L19\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"19\"><\/td>\n          <td id=\"file-vm2-fs-LC19\" class=\"blob-code blob-code-inner js-file-line\">                    // Handle error case here<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L20\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"20\"><\/td>\n          <td id=\"file-vm2-fs-LC20\" class=\"blob-code blob-code-inner js-file-line\">                    ()<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L21\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"21\"><\/td>\n          <td id=\"file-vm2-fs-LC21\" class=\"blob-code blob-code-inner js-file-line\">                do! loop()<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L22\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"22\"><\/td>\n          <td id=\"file-vm2-fs-LC22\" class=\"blob-code blob-code-inner js-file-line\">            }<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L23\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"23\"><\/td>\n          <td id=\"file-vm2-fs-LC23\" class=\"blob-code blob-code-inner js-file-line\">        loop()<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L24\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"24\"><\/td>\n          <td id=\"file-vm2-fs-LC24\" class=\"blob-code blob-code-inner js-file-line\">    let reporter = new MailboxProcessor&lt;_&gt;(update)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L25\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"25\"><\/td>\n          <td id=\"file-vm2-fs-LC25\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L26\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"26\"><\/td>\n          <td id=\"file-vm2-fs-LC26\" class=\"blob-code blob-code-inner js-file-line\">    // Start our report handler<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L27\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"27\"><\/td>\n          <td id=\"file-vm2-fs-LC27\" class=\"blob-code blob-code-inner js-file-line\">    do<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L28\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"28\"><\/td>\n          <td id=\"file-vm2-fs-LC28\" class=\"blob-code blob-code-inner js-file-line\">        reporter.Start()<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L29\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"29\"><\/td>\n          <td id=\"file-vm2-fs-LC29\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L30\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"30\"><\/td>\n          <td id=\"file-vm2-fs-LC30\" class=\"blob-code blob-code-inner js-file-line\">    // Create the agent used to update the model<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm2-fs-L31\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"31\"><\/td>\n          <td id=\"file-vm2-fs-LC31\" class=\"blob-code blob-code-inner js-file-line\">    let updateAgent = ForestManager.createUpdateAgent reporter<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/fdc403c3234553c6e52d/raw/7ceaebc3e6301b8b1156da0a9cdbd46cfac5810c/vm2.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/fdc403c3234553c6e52d#file-vm2-fs\" class=\"Link--inTextBlock\">\n          vm2.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>The reporter MailBoxProcessor we create listens for updates, and updates our current forest whenever an update occurs. Â We can handle different types if we wanted to post status updates to the user (which I&#8217;m currently not doing), and easily extend this to other types of updates or errors as needed.</p>
<p>We pass the reporter to the Manager to create a second MailboxProcessor: updateAgent. Â This will beÂ then used within our event stream, and allow us to post update requests back to the Model. Â Each user event maps to one update request, and, from the ViewModel perspective, requests are completely decoupled from the updates to display back to the user:</p>
<p><style> #wrap_githubgistfdc403c3234553c6e52d .gist-data {max-height: 100%;} </style><div id="wrap_githubgistfdc403c3234553c6e52d" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist28781451\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-vm3-fs\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-f  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"vm3.fs content, created by ReedCopsey on 08:19PM on December 09, 2015.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"vm3.fs\">\n        <tr>\n          <td id=\"file-vm3-fs-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-vm3-fs-LC1\" class=\"blob-code blob-code-inner js-file-line\">    // Create a handler for our UI event stream<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm3-fs-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-vm3-fs-LC2\" class=\"blob-code blob-code-inner js-file-line\">    let handleEvent event =<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm3-fs-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-vm3-fs-LC3\" class=\"blob-code blob-code-inner js-file-line\">        match event with<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm3-fs-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-vm3-fs-LC4\" class=\"blob-code blob-code-inner js-file-line\">        | Add(location) -&gt; <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm3-fs-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-vm3-fs-LC5\" class=\"blob-code blob-code-inner js-file-line\">            let height = 8.0 + rnd.NextDouble() * 4.0<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm3-fs-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-vm3-fs-LC6\" class=\"blob-code blob-code-inner js-file-line\">            updateAgent.Post &lt;| ForestUpdate.Add ({ Position = location ; Height = height ; Decorated = false }, forest.Value)                        <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm3-fs-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-vm3-fs-LC7\" class=\"blob-code blob-code-inner js-file-line\">        | Decorate(tree) -&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm3-fs-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-vm3-fs-LC8\" class=\"blob-code blob-code-inner js-file-line\">            updateAgent.Post &lt;| ForestUpdate.Decorate (tree, forest.Value)<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm3-fs-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-vm3-fs-LC9\" class=\"blob-code blob-code-inner js-file-line\">        | Unknown -&gt; <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm3-fs-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-vm3-fs-LC10\" class=\"blob-code blob-code-inner js-file-line\">            ()<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm3-fs-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-vm3-fs-LC11\" class=\"blob-code blob-code-inner js-file-line\">    do<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm3-fs-L12\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"12\"><\/td>\n          <td id=\"file-vm3-fs-LC12\" class=\"blob-code blob-code-inner js-file-line\">        self.EventStream<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm3-fs-L13\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"13\"><\/td>\n          <td id=\"file-vm3-fs-LC13\" class=\"blob-code blob-code-inner js-file-line\">        |&gt; Observable.subscribe handleEvent<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm3-fs-L14\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"14\"><\/td>\n          <td id=\"file-vm3-fs-LC14\" class=\"blob-code blob-code-inner js-file-line\">        |&gt; ignore<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm3-fs-L15\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"15\"><\/td>\n          <td id=\"file-vm3-fs-LC15\" class=\"blob-code blob-code-inner js-file-line\">\n<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm3-fs-L16\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"16\"><\/td>\n          <td id=\"file-vm3-fs-LC16\" class=\"blob-code blob-code-inner js-file-line\">    // Create an EventValueCommand for our UI to send us events<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-vm3-fs-L17\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"17\"><\/td>\n          <td id=\"file-vm3-fs-LC17\" class=\"blob-code blob-code-inner js-file-line\">    member val MouseCommand = self.Factory.EventValueCommand()<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/fdc403c3234553c6e52d/raw/7ceaebc3e6301b8b1156da0a9cdbd46cfac5810c/vm3.fs\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/fdc403c3234553c6e52d#file-vm3-fs\" class=\"Link--inTextBlock\">\n          vm3.fs\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>Once this is done, all of the logic for our program is complete. Â All that&#8217;s leftÂ is to wire up a user interface. Â <a href="https://github.com/fsprojects/FsXaml">FsXaml</a>Â provides some helpers which canÂ beÂ used to convert EventArgs into our TreeEvent discriminated union, so we create two converters, and use them via EventToCommand behaviors to push mouse clicks into our ViewModel.</p>
<p><style> #wrap_githubgistfdc403c3234553c6e52d .gist-data {max-height: 100%;} </style><div id="wrap_githubgistfdc403c3234553c6e52d" style="width:100%"><script>document.write('<link rel="stylesheet" href="https://github.githubassets.com/assets/gist-embed-b34f7d2eef9a0544.css">')
document.write('<div id=\"gist28781451\" class=\"gist\">\n    <div class=\"gist-file\" translate=\"no\" data-color-mode=\"light\" data-light-theme=\"light\">\n      <div class=\"gist-data\">\n        \n<div class=\"js-gist-file-update-container js-task-list-container\">\n      <div id=\"file-view-xaml\" class=\"file my-2\">\n    \n    <div itemprop=\"text\"\n      class=\"Box-body p-0 blob-wrapper data type-xml  \"\n      style=\"overflow: auto\" tabindex=\"0\" role=\"region\"\n      aria-label=\"view.xaml content, created by ReedCopsey on 08:19PM on December 09, 2015.\"\n    >\n\n        \n<div class=\"js-check-hidden-unicode js-blob-code-container blob-code-content\">\n\n  <template class=\"js-file-alert-template\">\n  <div data-view-component=\"true\" class=\"flash flash-warn flash-full d-flex flex-items-center\">\n  <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n    <span>\n      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.\n      <a class=\"Link--inTextBlock\" href=\"https://github.co/hiddenchars\" target=\"_blank\">Learn more about bidirectional Unicode characters<\/a>\n    <\/span>\n\n\n  <div data-view-component=\"true\" class=\"flash-action\">        <a href=\"{{ revealButtonHref }}\" data-view-component=\"true\" class=\"btn-sm btn\">    Show hidden characters\n<\/a>\n<\/div>\n<\/div><\/template>\n<template class=\"js-line-alert-template\">\n  <span aria-label=\"This line has hidden Unicode characters\" data-view-component=\"true\" class=\"line-alert tooltipped tooltipped-e\">\n    <svg aria-hidden=\"true\" data-component=\"Octicon\" height=\"16\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" data-view-component=\"true\" class=\"octicon octicon-alert\">\n    <path d=\"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\"><\/path>\n<\/svg>\n<\/span><\/template>\n\n  <table data-hpc class=\"highlight tab-size js-file-line-container\" data-tab-size=\"4\" data-paste-markdown-skip data-tagsearch-path=\"view.xaml\">\n        <tr>\n          <td id=\"file-view-xaml-L1\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"1\"><\/td>\n          <td id=\"file-view-xaml-LC1\" class=\"blob-code blob-code-inner js-file-line\">        &lt;ItemsControl <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view-xaml-L2\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"2\"><\/td>\n          <td id=\"file-view-xaml-LC2\" class=\"blob-code blob-code-inner js-file-line\">            Grid.Row=&quot;1&quot; <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view-xaml-L3\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"3\"><\/td>\n          <td id=\"file-view-xaml-LC3\" class=\"blob-code blob-code-inner js-file-line\">            HorizontalAlignment=&quot;Stretch&quot; <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view-xaml-L4\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"4\"><\/td>\n          <td id=\"file-view-xaml-LC4\" class=\"blob-code blob-code-inner js-file-line\">            VerticalAlignment=&quot;Stretch&quot; <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view-xaml-L5\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"5\"><\/td>\n          <td id=\"file-view-xaml-LC5\" class=\"blob-code blob-code-inner js-file-line\">            ItemsSource=&quot;{Binding Forest.Trees}&quot; <\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view-xaml-L6\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"6\"><\/td>\n          <td id=\"file-view-xaml-LC6\" class=\"blob-code blob-code-inner js-file-line\">            &gt; &lt;!-- One items control binding displays our trees.. --&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view-xaml-L7\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"7\"><\/td>\n          <td id=\"file-view-xaml-LC7\" class=\"blob-code blob-code-inner js-file-line\">            &lt;ItemsControl.ItemsPanel&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view-xaml-L8\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"8\"><\/td>\n          <td id=\"file-view-xaml-LC8\" class=\"blob-code blob-code-inner js-file-line\">                &lt;ItemsPanelTemplate&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view-xaml-L9\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"9\"><\/td>\n          <td id=\"file-view-xaml-LC9\" class=\"blob-code blob-code-inner js-file-line\">                    &lt;Canvas HorizontalAlignment=&quot;Stretch&quot; VerticalAlignment=&quot;Stretch&quot; Background=&quot;Gray&quot; &gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view-xaml-L10\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"10\"><\/td>\n          <td id=\"file-view-xaml-LC10\" class=\"blob-code blob-code-inner js-file-line\">                        &lt;i:Interaction.Triggers&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view-xaml-L11\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"11\"><\/td>\n          <td id=\"file-view-xaml-LC11\" class=\"blob-code blob-code-inner js-file-line\">                            &lt;i:EventTrigger EventName=&quot;MouseLeftButtonDown&quot;&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view-xaml-L12\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"12\"><\/td>\n          <td id=\"file-view-xaml-LC12\" class=\"blob-code blob-code-inner js-file-line\">                                &lt;fsx:EventToCommand Command=&quot;{Binding MouseCommand}&quot; EventArgsConverter=&quot;{StaticResource addConverter}&quot; /&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view-xaml-L13\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"13\"><\/td>\n          <td id=\"file-view-xaml-LC13\" class=\"blob-code blob-code-inner js-file-line\">                            &lt;/i:EventTrigger&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view-xaml-L14\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"14\"><\/td>\n          <td id=\"file-view-xaml-LC14\" class=\"blob-code blob-code-inner js-file-line\">                        &lt;/i:Interaction.Triggers&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view-xaml-L15\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"15\"><\/td>\n          <td id=\"file-view-xaml-LC15\" class=\"blob-code blob-code-inner js-file-line\">                    &lt;/Canvas&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view-xaml-L16\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"16\"><\/td>\n          <td id=\"file-view-xaml-LC16\" class=\"blob-code blob-code-inner js-file-line\">                &lt;/ItemsPanelTemplate&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view-xaml-L17\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"17\"><\/td>\n          <td id=\"file-view-xaml-LC17\" class=\"blob-code blob-code-inner js-file-line\">            &lt;/ItemsControl.ItemsPanel&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view-xaml-L18\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"18\"><\/td>\n          <td id=\"file-view-xaml-LC18\" class=\"blob-code blob-code-inner js-file-line\">            &lt;ItemsControl.ItemTemplate&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view-xaml-L19\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"19\"><\/td>\n          <td id=\"file-view-xaml-LC19\" class=\"blob-code blob-code-inner js-file-line\">                &lt;DataTemplate&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view-xaml-L20\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"20\"><\/td>\n          <td id=\"file-view-xaml-LC20\" class=\"blob-code blob-code-inner js-file-line\">                    &lt;Canvas&gt; &lt;! -- Our template for a tree --&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view-xaml-L21\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"21\"><\/td>\n          <td id=\"file-view-xaml-LC21\" class=\"blob-code blob-code-inner js-file-line\">                        &lt;i:Interaction.Triggers&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view-xaml-L22\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"22\"><\/td>\n          <td id=\"file-view-xaml-LC22\" class=\"blob-code blob-code-inner js-file-line\">                            &lt;i:EventTrigger EventName=&quot;MouseLeftButtonDown&quot;&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view-xaml-L23\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"23\"><\/td>\n          <td id=\"file-view-xaml-LC23\" class=\"blob-code blob-code-inner js-file-line\">                                &lt;fsx:EventToCommand Command=&quot;{Binding DataContext.MouseCommand, ElementName=Win}&quot; EventArgsConverter=&quot;{StaticResource decorateConverter}&quot; /&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view-xaml-L24\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"24\"><\/td>\n          <td id=\"file-view-xaml-LC24\" class=\"blob-code blob-code-inner js-file-line\">                            &lt;/i:EventTrigger&gt;<\/td>\n        <\/tr>\n        <tr>\n          <td id=\"file-view-xaml-L25\" class=\"blob-num js-line-number js-blob-rnum\" data-line-number=\"25\"><\/td>\n          <td id=\"file-view-xaml-LC25\" class=\"blob-code blob-code-inner js-file-line\">                        &lt;/i:Interaction.Triggers&gt;<\/td>\n        <\/tr>\n  <\/table>\n<\/div>\n\n\n    <\/div>\n\n  <\/div>\n\n<\/div>\n\n      <\/div>\n      <div class=\"gist-meta\">\n        <a href=\"https://gist.github.com/ReedCopsey/fdc403c3234553c6e52d/raw/7ceaebc3e6301b8b1156da0a9cdbd46cfac5810c/view.xaml\" style=\"float:right\" class=\"Link--inTextBlock\">view raw<\/a>\n        <a href=\"https://gist.github.com/ReedCopsey/fdc403c3234553c6e52d#file-view-xaml\" class=\"Link--inTextBlock\">\n          view.xaml\n        <\/a>\n        hosted with &#10084; by <a class=\"Link--inTextBlock\" href=\"https://github.com\">GitHub<\/a>\n      <\/div>\n    <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>400: Invalid request</pre></code></noscript></div></div></p>
<p>The key portion is line 12 and 23 &#8211; by using our converter, we can map a MouseEventArgs instance when the user clicks into our strongly typed event, and route that directly to our VM.</p>
<p>Once that&#8217;s done, if we run, we see:</p>
<p><a href="http://reedcopsey.com/blog/wp-content/uploads/2015/12/AdvEmpty.png" rel="attachment wp-att-360"><img loading="lazy" decoding="async" class="aligncenter size-medium wp-image-360" src="http://reedcopsey.com/blog/wp-content/uploads/2015/12/AdvEmpty-296x300.png" alt="AdvEmpty" width="296" height="300" srcset="http://reedcopsey.com/blog/wp-content/uploads/2015/12/AdvEmpty-296x300.png 296w, http://reedcopsey.com/blog/wp-content/uploads/2015/12/AdvEmpty.png 486w" sizes="(max-width: 296px) 100vw, 296px" /></a></p>
<p>Clicking in the window should add a tree &#8211; and clicking on a tree will &#8220;decorate&#8221; it:</p>
<p><a href="http://reedcopsey.com/blog/wp-content/uploads/2015/12/AdventDecorated.png" rel="attachment wp-att-361"><img loading="lazy" decoding="async" class="aligncenter size-medium wp-image-361" src="http://reedcopsey.com/blog/wp-content/uploads/2015/12/AdventDecorated-296x300.png" alt="AdventDecorated" width="296" height="300" srcset="http://reedcopsey.com/blog/wp-content/uploads/2015/12/AdventDecorated-296x300.png 296w, http://reedcopsey.com/blog/wp-content/uploads/2015/12/AdventDecorated.png 486w" sizes="(max-width: 296px) 100vw, 296px" /></a></p>
<p>Once we get more than 10 trees, adding another will prune the forest and remove trees,Â which illustrates how eventsÂ separate from the UI automatically populate through to the user interface automatically.</p>
<p>All of the source code is available on GitHub atÂ <a href="https://github.com/ReedCopsey/AdventTrees">https://github.com/ReedCopsey/AdventTrees</a>. Â Please download, try it out, andÂ enjoy!</p>
<p>And remember to enjoy the rest of theÂ F#-rich goodness that is the 2015 <a href="https://sergeytihon.wordpress.com/tag/fsadvent/">F# Advent</a>!</p>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2015/12/09/christmas-trees-in-wpf-using-fsharp-viewmodule/feed/</wfw:commentRss>
			<slash:comments>9</slash:comments>
		
		
			</item>
		<item>
		<title>F# 2014 &#8211; A Retrospective and Call to Action</title>
		<link>http://reedcopsey.com/2014/12/31/fsharp-2014-a-retrospective-and-call-to-action/</link>
					<comments>http://reedcopsey.com/2014/12/31/fsharp-2014-a-retrospective-and-call-to-action/#comments</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Wed, 31 Dec 2014 08:15:49 +0000</pubDate>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[F#]]></category>
		<category><![CDATA[F# Software Foundation]]></category>
		<category><![CDATA[FSSF]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/?p=340</guid>

					<description><![CDATA[I have the privilege of being allowed to writeÂ the final post forÂ theÂ F# Advent Calendar in English. To celebrate, I thought I&#8217;d skip aÂ technical post and end the year, and the Advent Calendar, with a brief, personal look back on 2014 and the wonderful time I&#8217;ve had within the F# community over this past year. I [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I have the privilege of being allowed to writeÂ the final post forÂ theÂ <a href="https://sergeytihon.wordpress.com/2014/11/24/f-advent-calendar-in-english-2014/">F# Advent Calendar in English</a>. To celebrate, I thought I&#8217;d skip aÂ technical post and end the year, and the Advent Calendar, with a brief, personal look back on 2014 and the wonderful time I&#8217;ve had within the F# community over this past year.</p>
<p><span id="more-340"></span>I fondly remember sitting in a room with a few dedicated F# enthusiasts back in November of 2013. The passion for F# and excitement with seeing its steady growth was addictive. Nobody in the room could avoid being excitedÂ asÂ <a href="https://twitter.com/brandewinder">Mathias</a>Â proposedÂ to make 2014 be &#8220;the year of F#.&#8221;Â The community was energized. Little did I realize, at that point, how prophetic that simple statement would become.</p>
<p>This year has been an amazing year for F#. This communityÂ astounds me on a regular basis, and this year has surpassed all concepts of expectations I held previously. While I won&#8217;t even attempt to list all of the highlights, some of my personal favorite events this year have included:</p>
<ul>
<li><a href="http://blogs.msdn.com/b/fsharpteam/archive/2014/04/03/facilitating-open-contributions-for-the-f-compiler-library-and-visual-f-tools.aspx" target="_blank">Visual F# Tools accepting pull requests</a>Â and then even releasing an <a href="http://blogs.msdn.com/b/fsharpteam/archive/2014/08/20/announcing-the-release-of-visual-f-tools-3-1-2.aspx" target="_blank">out of band release with community contributions</a></li>
<li>Xamarin 3 including <a href="http://7sharpnine.com/posts/xamarin-3-fsharp-awsomeness/" target="_blank">&#8220;F# Awesomeness&#8221;</a>Â in all downloads of Xamarin Studio</li>
<li>IntelliFactory <a href="http://www.websharper.com/blog-entry/4124" target="_blank">releasing WebSharper 3 under an Apache 2.0 license</a></li>
<li>The announcement of an <a href="http://blogs.msdn.com/b/dotnet/archive/2014/11/12/net-core-is-open-source.aspx" target="_blank">open sourced .NET Core</a></li>
<li>The community workingÂ togetherÂ to create a <a href="https://groups.google.com/d/msg/fsharp-opensource/E-onlHD-WIY/dUDTh3k3eZIJ" target="_blank">new F# logo</a></li>
<li>Entire &#8220;F#Â tracks&#8221; at many conferences with numerous speakers</li>
<li>A community driven push towards <a href="https://visualfsharp.codeplex.com/wikipage?title=Status" target="_blank">F# 4.0</a>, with a <a href="https://visualfsharp.codeplex.com/wikipage?title=Contributors" target="_blank">large list of contributors</a></li>
<li>Intense open source contributions in the F# ecosystem &#8211; with <a href="https://github.com/fsprojects/VisualFSharpPowerTools/graphs/commit-activity" target="_blank">consistent improvements</a>Â throughout the year, and some projects <a href="https://github.com/fsprojects/Paket/graphs/commit-activity" target="_blank">getting over 200 commits</a> in a singleÂ week!</li>
<li>New <a href="http://c4fsharp.net/groups.html" target="_blank">F# User Groups</a> being created around the world, with more speakers, talks, and topics than ever before</li>
<li>Too many other things to list, including wonderful blog posts, two F# Advent calendars -Â inÂ <a href="https://sergeytihon.wordpress.com/2014/11/24/f-advent-calendar-in-english-2014/">English</a>Â and in <a href="http://connpass.com/event/9758/" target="_blank">Japanese</a>,Â an <a href="http://chat.stackoverflow.com/rooms/51909/f" target="_blank">active F# chat room</a>, new <a href="http://c4fsharp.net/#list-of-dojos" target="_blank">coding dojos</a>, and more&#8230;</li>
</ul>
<p>IÂ amÂ thankful to everybody in the F# community. Thank you for a wonderful year. It has been my honor and my pleasure to work with many of you. I&#8217;ve met wonderful new colleagues, and look forward to meeting many more of you in the upcoming year.</p>
<p>Which brings me to my personal favorite F# event of the year &#8211; legally forming the F# Software Foundation. Late in the year, a <a href="http://foundation.fsharp.org/board_and_officers" target="_blank">group of dedicated community members</a> helped move the F# Software Foundation (FSSF)Â from an informal organization to a <a href="https://groups.google.com/d/msg/fsharp-opensource/mbldSfUmwwA/_ND4VzdedpMJ" target="_blank">legally established entity</a>, and are diligentlyÂ workingÂ to makeÂ the FSSFÂ the organizationÂ the F# community deserves. I still feel honored to be a part of this endeavor, and am dedicated to helping in any and every way possible moving forward.</p>
<p>Yesterday, we announced the new membership site, where anybody can <a href="http://foundation.fsharp.org/join" target="_blank">join the FSSF and become a member</a>.Â We immediately had <a href="http://foundation.fsharp.org/member_roster" target="_blank">people signing up</a>, and weÂ have been receiving very positive feedback on everything being done with FSSF.</p>
<p>I&#8217;d like to propose that everybody in the community, whether you&#8217;ve been using F# for years or minutes, to join me in a call to action.</p>
<p style="text-align: center;"><strong><a href="http://foundation.fsharp.org/join" target="_blank">Join the F# Software Foundation.</a></strong></p>
<p>The F# Software FoundationÂ canÂ only ever be as good as itsÂ membership. I encourage anybody with an interest in F# to <a href="http://foundation.fsharp.org/join" target="_blank">join as a member</a>, and <a href="http://foundation.fsharp.org/contact" target="_blank">share your ideas for the F# Software Foundation.</a></p>
<ul>
<li>If you&#8217;re a dedicated member of the F# community, hopefully your name is already on the <a href="http://foundation.fsharp.org/member_roster" target="_blank">member roster</a>. If not, it only takes a few minutes to be listed.</li>
<li>Are you a Scala developer who is interested to see what&#8217;s happening in the newly opened source .NET world?Â <a href="http://foundation.fsharp.org/join" target="_blank">Join our community</a>.</li>
<li>AreÂ you a C# developerÂ in love with LINQÂ who mightÂ like to learn more functional programming?Â <a href="http://foundation.fsharp.org/join" target="_blank">Join our community</a>Â and see what F# has to offer.</li>
<li>Are youÂ a JavaScript developer who&#8217;d love to see how type safety via <a href="http://websharper.com/" target="_blank">WebSharper</a> or <a href="http://funscript.info/" target="_blank">FunScript</a> could change the way you think aboutÂ programming?Â <a href="http://foundation.fsharp.org/join" target="_blank">Join our community</a>.</li>
<li>WouldÂ you likeÂ to work with data from multipleÂ sources, withÂ type safety andÂ IDE integration? Investigate <a href="http://channel9.msdn.com/posts/Tomas-Petricek-How-F-Learned-to-Stop-Worrying-and-Love-the-Data" target="_blank">type providers</a>Â andÂ <a href="http://foundation.fsharp.org/join" target="_blank">join our community</a>.</li>
<li><a href="http://foundation.fsharp.org/diversity" target="_blank">Everybody is welcome</a> and encouraged to become a member. If you agree with the <a href="http://foundation.fsharp.org/" target="_blank">Mission of the FSSF</a>,Â <a href="http://foundation.fsharp.org/join" target="_blank">join us</a>!</li>
</ul>
<p>2014 has been an amazing year for F# &#8211;</p>
<p>Let&#8217;sÂ roll out the end of the year with a shower of new members, and make 2015 even better!</p>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2014/12/31/fsharp-2014-a-retrospective-and-call-to-action/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title>Slides and Code from &#8220;Using C#&#8217;s Async Effectively&#8221;</title>
		<link>http://reedcopsey.com/2013/10/02/slides-and-code-from-using-cs-async-effectively/</link>
					<comments>http://reedcopsey.com/2013/10/02/slides-and-code-from-using-cs-async-effectively/#comments</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Wed, 02 Oct 2013 23:04:46 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Async]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Community]]></category>
		<category><![CDATA[.NET 4.5]]></category>
		<category><![CDATA[C# 5]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/?p=329</guid>

					<description><![CDATA[The slides and code from my talk on the new async language features in C# and VB.Net are now available on https://github.com/ReedCopsey/Effective-Async This includes the complete slide deck, and all 4 projects, including: FakeService: Simple WCF service to run locally and simulate network service calls. AsyncService: Simple WCF service which wraps FakeService to demonstrate converting [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>The slides and code from my talk on the new async language features in C# and VB.Net are now available on <a href="https://github.com/ReedCopsey/Effective-Async">https://github.com/ReedCopsey/Effective-Async</a></p>
<p><span id="more-329"></span></p>
<p>This includes the <a href="https://github.com/ReedCopsey/Effective-Async/blob/master/AsyncTalk.pptx">complete slide deck</a>, and all 4 projects, including:</p>
<ul>
<li><strong>FakeService:</strong> Simple WCF service to run locally and simulate network service calls.</li>
<li><strong>AsyncService:</strong> Simple WCF service which wraps FakeService to demonstrate converting sync to async</li>
<li><strong>SimpleWPFExample: </strong>Simplest example of converting a method call to async from a synchronous version</li>
<li><strong>AsyncExamples:</strong> Windows Store application demonstrating main concepts, pitfalls, tips, and tricks from the slide deck</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2013/10/02/slides-and-code-from-using-cs-async-effectively/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>Launching a WPF Window in a Separate Thread, Part 1</title>
		<link>http://reedcopsey.com/2011/11/28/launching-a-wpf-window-in-a-separate-thread-part-1/</link>
					<comments>http://reedcopsey.com/2011/11/28/launching-a-wpf-window-in-a-separate-thread-part-1/#comments</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Mon, 28 Nov 2011 20:32:38 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[WPF]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/2011/11/28/launching-a-wpf-window-in-a-separate-thread-part-1/</guid>

					<description><![CDATA[Typically, I strongly recommend keeping the user interface within an applicationâ€™s main thread, and using multiple threads to move the actual â€œworkâ€ into background threads.&#160; However, there are rare times when creating a separate, dedicated thread for a Window can be beneficial.&#160; This is even acknowledged in the MSDN samples, such as the Multiple Windows, [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Typically, I strongly recommend keeping the user interface within an applicationâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s main thread, and using multiple threads to move the actual â€œworkâ€ into background threads.&#160; However, there are rare times when creating a separate, dedicated thread for a Window can be beneficial.&#160; This is even acknowledged in the MSDN samples, such as the Multiple Windows, Multiple Threads* sample.&#160; However, doing this <em>correctly</em> is difficult.&#160; Even the referenced MSDN sample has major flaws, and will fail horribly in certain scenarios.&#160; To ease this, I wrote a small class that alleviates some of the difficulties involved.</p>
<p><span id="more-321"></span></p>
<p>The MSDN Multiple Windows, Multiple Threads Sample* showed how to launch a new thread with a WPF Window, and will work in most cases.&#160; The sample code (commented and slightly modified) works out to the following:</p>
<pre class="csharpcode"><span class="rem">// Create a thread</span>
Thread newWindowThread = <span class="kwrd">new</span> Thread(<span class="kwrd">new</span> ThreadStart( () =&gt;
{
    <span class="rem">// Create and show the Window</span>
    Window1 tempWindow = <span class="kwrd">new</span> Window1();
    tempWindow.Show();
    <span class="rem">// Start the Dispatcher Processing</span>
    System.Windows.Threading.Dispatcher.Run();
}));
<span class="rem">// Set the apartment state</span>
newWindowThread.SetApartmentState(ApartmentState.STA);
<span class="rem">// Make the thread a background thread</span>
newWindowThread.IsBackground = <span class="kwrd">true</span>;
<span class="rem">// Start the thread</span>
newWindowThread.Start();</pre>
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>This sample creates a thread, marks it as single threaded apartment state, and starts the Dispatcher on that thread. That is the minimum requirements to get a Window displaying and handling messages correctly, but, unfortunately, has some serious flaws. </p>
<p>*Note: The referenced sample is no longer available as of 2013.  A new <a href="http://msdn.microsoft.com/en-us/library/ms771272%28v=vs.90%29.aspx">Multithreaded Web Browser Sample</a> shows a similar technique and code</a></p>
<p>The first issue â€“ the created thread will run continuously until the application shuts down, given the code in the sample.&#160; The problem is that the ThreadStart delegate used ends with running the Dispatcher.&#160; However, nothing ever stops the Dispatcher processing.&#160; The thread was created as a Background thread, which prevents it from keeping the application alive, but the Dispatcher will continue to pump dispatcher frames until the application shuts down.</p>
<p>In order to fix this, we need to call <a href="http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.invokeshutdown.aspx">Dispatcher.InvokeShutdown</a> after the Window is closed.&#160; This would require modifying the above sample to subscribe to the Windowâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s Closed event, and, at that point, shutdown the Dispatcher:</p>
<pre class="csharpcode"><span class="rem">// Create a thread</span>
Thread newWindowThread = <span class="kwrd">new</span> Thread(<span class="kwrd">new</span> ThreadStart( () =&gt;
{
    Window1 tempWindow = <span class="kwrd">new</span> Window1();
    <span class="rem">// When the window closes, shut down the dispatcher</span>
    tempWindow.Closed += (s,e) =&gt; 
       Dispatcher.CurrentDispatcher.BeginInvokeShutdown(DispatcherPriority.Background);

    tempWindow.Show();
    <span class="rem">// Start the Dispatcher Processing</span>
    System.Windows.Threading.Dispatcher.Run();
}));
<span class="rem">// Setup and start thread as before</span></pre>
<p>This eliminates the first issue.&#160; Now, when the Window is closed, the new threadâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s Dispatcher will shut itself down, which in turn will cause the thread to complete.</p>
<p>The above code will work correctly for most situations.&#160; However, there is still a potential problem which could arise depending on the content of the Window1 class.&#160; This is particularly nasty, as the code could easily work for most windows, but fail on others.</p>
<p>The problem is, at the point where the Window is constructed, there is no active SynchronizationContext.&#160; This is unlikely to be a problem in most cases, but is an absolute requirement if there is code within the constructor of Window1 which relies on a context being in place.</p>
<p>While this sounds like an edge case, itâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s fairly common.&#160; For example, if a BackgroundWorker is started within the constructor, or a TaskScheduler is built using TaskScheduler.FromCurrentSynchronizationContext() with the expectation of synchronizing work to the UI thread, an exception will be raised at some point.&#160; Both of these classes rely on the existence of a proper context being installed to SynchronizationContext.Current, which happens automatically, but not until Dispatcher.Run is called.&#160; In the above case, SynchronizationContext.Current will return null during the Windowâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s construction, which can cause exceptions to occur or unexpected behavior.</p>
<p>Luckily, this is fairly easy to correct.&#160; We need to do three things, in order, prior to creating our Window:</p>
<ul>
<li>Create and initialize the Dispatcher for the new thread manually </li>
<li>Create a synchronization context for the thread which uses the Dispatcher </li>
<li>Install the synchronization context </li>
</ul>
<p>Creating the Dispatcher is quite simple â€“ The <a href="http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.currentdispatcher.aspx">Dispatcher.CurrentDispatcher</a> property gets the current threadâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s Dispatcher and â€œ<em>creates a new Dispatcher if one is not already associated with the thread.</em>â€&#160; Once we have the correct Dispatcher, we can create a SynchronizationContext which uses the dispatcher by creating a <a href="http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatchersynchronizationcontext.aspx">DispatcherSynchronizationContext</a>.&#160; Finally, this synchronization context can be installed as the current threadâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s context via <a href="http://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.setsynchronizationcontext.aspx">SynchronizationContext.SetSynchronizationContext</a>.&#160; These three steps can easily be added to the above via a single line of code:</p>
<pre class="csharpcode"><span class="rem">// Create a thread</span>
Thread newWindowThread = <span class="kwrd">new</span> Thread(<span class="kwrd">new</span> ThreadStart( () =&gt;
{
    <span class="rem">// Create our context, and install it:</span>
    SynchronizationContext.SetSynchronizationContext(
        <span class="kwrd">new</span> DispatcherSynchronizationContext(
            Dispatcher.CurrentDispatcher));

    Window1 tempWindow = <span class="kwrd">new</span> Window1();
    <span class="rem">// When the window closes, shut down the dispatcher</span>
    tempWindow.Closed += (s,e) =&gt; 
       Dispatcher.CurrentDispatcher.BeginInvokeShutdown(DispatcherPriority.Background);

    tempWindow.Show();
    <span class="rem">// Start the Dispatcher Processing</span>
    System.Windows.Threading.Dispatcher.Run();
}));
<span class="rem">// Setup and start thread as before</span></pre>
<p>This now forces the synchronization context to be in place before the Window is created and correctly shuts down the Dispatcher when the window closes.</p>
<p>However, there are quite a few steps.&#160; In my next post, Iâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />ll show how to make this operation more reusable by creating a class with a far simpler APIâ€¦</p>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2011/11/28/launching-a-wpf-window-in-a-separate-thread-part-1/feed/</wfw:commentRss>
			<slash:comments>45</slash:comments>
		
		
			</item>
		<item>
		<title>Reflections on GiveCamp</title>
		<link>http://reedcopsey.com/2011/10/25/reflections-on-givecamp/</link>
					<comments>http://reedcopsey.com/2011/10/25/reflections-on-givecamp/#comments</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Wed, 26 Oct 2011 00:20:48 +0000</pubDate>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[Professional]]></category>
		<category><![CDATA[Charity]]></category>
		<category><![CDATA[GiveCamp]]></category>
		<category><![CDATA[Programming]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/2011/10/25/reflections-on-givecamp/</guid>

					<description><![CDATA[I participated in the Seattle GiveCamp over the weekend, and am entirely impressed.&#160; GiveCamp is a great event â€“ I especially like how rewarding it is for everybody involved.&#160; I strongly encourage any and all developers to watch for future GiveCamp events, and consider participating, for many reasonsâ€¦ GiveCamp provides real value to organizations that [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I participated in the <a href="http://www.seattlegivecamp.org/">Seattle GiveCamp</a> over the weekend, and am entirely impressed.&#160; <a href="http://givecamp.org/">GiveCamp</a> is a great event â€“ I especially like how rewarding it is for everybody involved.&#160; I strongly encourage any and all developers to <a href="https://twitter.com/#!/givecamp">watch for future GiveCamp</a> events, and consider participating, for many reasonsâ€¦</p>
<p><span id="more-314"></span></p>
<ul>
<li><strong>GiveCamp provides real value to organizations that truly need help.&#160; </strong></li>
</ul>
<p>The Seattle event alone succeeded in helping <a href="http://seattlegivecamp.wikispaces.com/">sixteen non-profit organizations</a> in many different ways.&#160; The projects involved varied dramatically, including website redesigns, SEO, reworking data management workflows, and even game development.&#160; </p>
<p>Many non-profits have a strong need for good, quality technical help.&#160; However, nearly every non-profit organization has an incredibly limited budget.&#160; GiveCamp is a way to really give back, and provide incredibly valuable help to organizations that truly benefit.</p>
<p>My experience has shown many developers to be incredibly generous â€“ this is a chance to dedicate your energy to helping others in a way that really takes advantage of your expertise.&#160; Your time as a developer is incredibly valuable, and this puts something of incredible value directly into the hands of places its needed.</p>
<p>First, and foremost, GiveCamp is about providing technical help to non-profit organizations in need.</p>
<ul>
<li><strong>GiveCamp can make you a better developer.&#160; </strong></li>
</ul>
<p>This is a fantastic opportunity for us, as developers, to work with new people, in a new setting.&#160; The incredibly short time frame (one weekend for a deliverable project) and intense motivation to succeed provides a huge opportunity for learning from peers.&#160; </p>
<p>Iâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />d personally like to thank off the developers with whom I worked â€“ I learned something from each and every one of you.&#160; I hope to see and work with all of you again someday.</p>
<ul>
<li><strong>GiveCamp provides an opportunity for you to work outside of your comfort zone. </strong></li>
</ul>
<p>While itâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s always nice to be an expert, itâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s also valuable to work on a project where you have little or no direct experience.&#160; My team focused on a complete reworking of our organizations message and a complete new website redesign and deployment using <a href="http://wordpress.org/">WordPress</a>.&#160; </p>
<p>While Iâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />d used WordPress for my blog, and had some experience, this is completely unrelated to my professional work.&#160; In fact, nobody on our team normally worked directly with the technologies involved â€“ yet together we managed to succeed in delivering our goals.&#160; </p>
<p>As developers, itâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s easy to want to stay abreast of new technology surrounding our expertise, but its rare that we get a chance to sit down and work on something <em>practical</em> that is completely outside of our normal realm of work.&#160; Iâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />m a desktop developer by trade, and spent much of the weekend working with CSS and Photoshop.&#160; Many of the projects organizations <em>need</em> donâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t match perfectly with the skill set in the room â€“ yet all of the software professionals rose to the occasion and delivered practical, usable applications.</p>
<ul>
<li><strong>GiveCamp is a short term, known commitment. </strong></li>
</ul>
<p>While this seems obvious, I think itâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s an important aspect to remember.&#160; This is a huge part of what makes it successful â€“ you can work, completely focused, on a project, then walk away completely when youâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />re done.&#160; There is no expectation of continued involvement.&#160; While many of the professionals Iâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />ve talked to are willing to contribute some amount of their time beyond the camp, this is not expected.</p>
<p>The freedom this provides is immense.&#160; In addition, the motivation this brings is incredibly valuable.&#160; Every developer in the room was very focused on delivering in time â€“ you have one shot to get it as good as possible, and leave it with the organization in a way that can be maintained by them.&#160; This is a rare experience â€“ and excellent practice at time management for everyone involved.</p>
<ul>
<li><strong>GiveCamp provides a great way to meet and network with your peers. </strong></li>
</ul>
<p>Not only do you get to network with other software professionals in your area â€“ you get to network with amazing people.&#160; Every single person in the room is there to try to help people.&#160; The balance of altruism, intelligence, and expertise in the room is something Iâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />ve never before experienced.</p>
<p>During the presentations of what was accomplished, I felt blessed to participate.&#160; I know many people in the room were incredibly touched by the level of dedication and accomplishment over the weekend.</p>
<ul>
<li><strong>GiveCamp is fun. </strong></li>
</ul>
<p>At the end of the experience, I would have signed up again, even if it was a painful, tedious weekend â€“ merely due to the amazing accomplishments achieved throughout the event.&#160; However, the event is <em>fun.</em>&#160; </p>
<p>Everybody I talked to, the entire weekend, was having a good time.&#160; While there were many faces focused into a near grimace at times (including mine, Iâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />ll admit), this was always in response to a particularly challenging problem or task.&#160; The challenges just added to the overall enjoyment of the weekend â€“ part of why I became a developer in the first place is my love for challenge and puzzles, and a short deadline using unfamiliar technology provided plenty of opportunity for puzzles.&#160; As soon as people would stand up, it was another smile.</p>
<p>&#160;</p>
<p>If youâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />re a developer, Iâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />d recommend looking at <a href="http://givecamp.org/">GiveCamp</a> more closely.&#160; Watch for an event in your area.&#160; If there isnâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t one, consider building a team and <a href="http://givecamp.org/home/for-organizers/">organizing an event</a>.&#160; The experience is worth the commitment.&#160; </p>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2011/10/25/reflections-on-givecamp/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Setting useLegacyV2RuntimeActivationPolicy At Runtime</title>
		<link>http://reedcopsey.com/2011/09/15/setting-uselegacyv2runtimeactivationpolicy-at-runtime/</link>
					<comments>http://reedcopsey.com/2011/09/15/setting-uselegacyv2runtimeactivationpolicy-at-runtime/#comments</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Thu, 15 Sep 2011 20:58:12 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[.NET 4]]></category>
		<category><![CDATA[C# 4]]></category>
		<category><![CDATA[Interop]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/2011/09/15/setting-uselegacyv2runtimeactivationpolicy-at-runtime/</guid>

					<description><![CDATA[Version 4.0 of the .NET Framework included a new CLR which is almost entirely backwards compatible with the 2.0 version of the CLR.&#160; However, by default, mixed-mode assemblies targeting .NET 3.5sp1 and earlier will fail to load in a .NET 4 application.&#160; Fixing this requires setting useLegacyV2RuntimeActivationPolicy in your app.Config for the application.&#160; While there [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Version 4.0 of the .NET Framework included a new CLR which is <em>almost</em> entirely backwards compatible with the 2.0 version of the CLR.&#160; However, by default, mixed-mode assemblies targeting .NET 3.5sp1 and earlier will fail to load in a .NET 4 application.&#160; Fixing this requires setting <a href="http://msdn.microsoft.com/en-us/library/bbx34a2h.aspx">useLegacyV2RuntimeActivationPolicy</a> in your app.Config <em>for the application.&#160; </em>While there are <a href="http://www.marklio.com/marklio/PermaLink,guid,ecc34c3c-be44-4422-86b7-900900e451f9.aspx">many good reasons for this decision</a>, there are times when this is extremely frustrating, especially when writing a library.&#160; As such, there are (rare) times when it would be beneficial to set this in code, at runtime, as well as verify that itâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s running correctly prior to receiving a <a href="http://msdn.microsoft.com/en-us/library/system.io.fileloadexception.aspx">FileLoadException</a>.</p>
<p><span id="more-312"></span></p>
<p>Typically, loading a pre-.NET 4 mixed mode assembly is handled simply by changing your app.Config file, and including the relevant attribute in the startup element:</p>
<pre class="csharpcode"><span class="kwrd">&lt;?</span><span class="html">xml</span> <span class="attr">version</span><span class="kwrd">=&quot;1.0&quot;</span> <span class="attr">encoding</span><span class="kwrd">=&quot;utf-8&quot;</span> ?<span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">configuration</span><span class="kwrd">&gt;</span>
  <span class="kwrd">&lt;</span><span class="html">startup</span> <span class="attr">useLegacyV2RuntimeActivationPolicy</span><span class="kwrd">=&quot;true&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">supportedRuntime</span> <span class="attr">version</span><span class="kwrd">=&quot;v4.0&quot;</span><span class="kwrd">/&gt;</span>
  <span class="kwrd">&lt;/</span><span class="html">startup</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">configuration</span><span class="kwrd">&gt;</span></pre>
<style type="text/css">
.csharpcode {
	background-color: #ffffff; font-family: consolas, "Courier New", courier, monospace; color: black; font-size: small
}
.csharpcode pre {
	background-color: #ffffff; font-family: consolas, "Courier New", courier, monospace; color: black; font-size: small
}
.csharpcode pre {
	margin: 0em
}
.csharpcode .rem {
	color: #008000
}
.csharpcode .kwrd {
	color: #0000ff
}
.csharpcode .str {
	color: #006080
}
.csharpcode .op {
	color: #0000c0
}
.csharpcode .preproc {
	color: #cc6633
}
.csharpcode .asp {
	background-color: #ffff00
}
.csharpcode .html {
	color: #800000
}
.csharpcode .attr {
	color: #ff0000
}
.csharpcode .alt {
	background-color: #f4f4f4; margin: 0em; width: 100%
}
.csharpcode .lnum {
	color: #606060
}</style>
<p>This causes your application to run correctly, and load the older, mixed-mode assembly without issues. For full details on whatâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s happening here and why, I recommend reading <a href="http://www.marklio.com/marklio/PermaLink,guid,ecc34c3c-be44-4422-86b7-900900e451f9.aspx">Mark Millerâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s detailed explanation</a> of this attribute and the reasoning behind it.</p>
<p>Before I show any code, let me say: </p>
<ul>
<li><strong>I strongly recommend using the official approach of using app.config to set this policy.</strong></li>
</ul>
<p>That being said, there are (rare) times when, for one reason or another, changing the application configuration file is less than ideal.</p>
<p>While this is the supported approach to handling this issue, the CLR Hosting API includes a means of setting this programmatically via the <a href="http://msdn.microsoft.com/en-us/library/dd233121.aspx">ICLRRuntimeInfo</a> interface.&#160; Normally, this is used if youâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />re hosting the CLR in a native application in order to set this, at runtime, prior to loading the assemblies.&#160; However, the F# Samples include a nice <a href="http://code.msdn.microsoft.com/3DVisualization-Visual-79471042/sourcecode?fileId=18993&amp;pathId=995930383">trick showing how to load this API and bind this policy</a>, at runtime.&#160; This was required in order to host the Managed DirectX API, which is built against an older version of the CLR.</p>
<p>This is fairly easy to port to C#.&#160; Instead of a direct port, I also added a little addition â€“ by trapping the COM exception received if unable to bind (which will occur if the 2.0 CLR is already bound), I also allow a runtime check of whether this property was setup properly:</p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">class</span> RuntimePolicyHelper
{
    <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">bool</span> LegacyV2RuntimeEnabledSuccessfully { get; <span class="kwrd">private</span> set; }

    <span class="kwrd">static</span> RuntimePolicyHelper()
    {
        ICLRRuntimeInfo clrRuntimeInfo =
            (ICLRRuntimeInfo)RuntimeEnvironment.GetRuntimeInterfaceAsObject(
                Guid.Empty, 
                <span class="kwrd">typeof</span>(ICLRRuntimeInfo).GUID);
        <span class="kwrd">try</span>
        {
            clrRuntimeInfo.BindAsLegacyV2Runtime();
            LegacyV2RuntimeEnabledSuccessfully = <span class="kwrd">true</span>;
        }
        <span class="kwrd">catch</span> (COMException)
        {
            <span class="rem">// This occurs with an HRESULT meaning </span>
            <span class="rem">// &quot;A different runtime was already bound to the legacy CLR version 2 activation policy.&quot;</span>
            LegacyV2RuntimeEnabledSuccessfully = <span class="kwrd">false</span>;
        }
    }

    [ComImport]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [Guid(<span class="str">&quot;BD39D1D2-BA2F-486A-89B0-B4B0CB466891&quot;</span>)]
    <span class="kwrd">private</span> <span class="kwrd">interface</span> ICLRRuntimeInfo
    {
        <span class="kwrd">void</span> xGetVersionString();
        <span class="kwrd">void</span> xGetRuntimeDirectory();
        <span class="kwrd">void</span> xIsLoaded();
        <span class="kwrd">void</span> xIsLoadable();
        <span class="kwrd">void</span> xLoadErrorString();
        <span class="kwrd">void</span> xLoadLibrary();
        <span class="kwrd">void</span> xGetProcAddress();
        <span class="kwrd">void</span> xGetInterface();
        <span class="kwrd">void</span> xSetDefaultStartupFlags();
        <span class="kwrd">void</span> xGetDefaultStartupFlags();

        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        <span class="kwrd">void</span> BindAsLegacyV2Runtime();
    }
}</pre>
<p>Using this, itâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s possible to not only set this at runtime, but also verify, prior to loading your mixed mode assembly, whether this will succeed.</p>
<p>In my case, this was quite useful â€“ I am working on a library <em>purely for internal use </em>which uses a numerical package that is supplied with both a completely managed as well as a native solver.&#160; The native solver uses a CLR 2 mixed-mode assembly, but is dramatically faster than the pure managed approach.&#160; By checking RuntimePolicyHelper.LegacyV2RuntimeEnabledSuccessfully at runtime, I can decide whether to enable the native solver, and only do so if I successfully bound this policy.</p>
<p>There are some tricks required here â€“ To enable this sort of fallback behavior, you must make these checks in a type that doesnâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t cause the mixed mode assembly to be loaded.&#160; In my case, this forced me to encapsulate the library I was using entirely in a separate class, perform the check, then pass through the required calls to that class.&#160; Otherwise, the library will load before the hosting process gets enabled, which in turn will fail.</p>
<p>This code will also, of course, try to enable the runtime policy before the first time you use this class â€“ which typically means just before the first time you check the boolean value.&#160; As a result, checking this early on in the application is more likely to allow it to work.</p>
<p>Finally, if youâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />re using a library, this has to be called prior to the 2.0 CLR loading.&#160; This will cause it to fail if you try to use it to enable this policy in a plugin for most third party applications that donâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t have their app.config setup properly, as they will likely have already loaded the 2.0 runtime.</p>
<p>As an example, take a simple audio player.&#160; The code below shows how this can be used to properly, at runtime, only use the â€œnativeâ€ API if this will succeed, and fallback (or raise a nicer exception) if this will fail:</p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> AudioPlayer
{
    <span class="kwrd">private</span> IAudioEngine audioEngine;

    <span class="kwrd">public</span> AudioPlayer()
    {
        <span class="kwrd">if</span> (RuntimePolicyHelper.LegacyV2RuntimeEnabledSuccessfully)
        {
            <span class="rem">// This will load a CLR 2 mixed mode assembly</span>
            <span class="kwrd">this</span>.audioEngine = <span class="kwrd">new</span> AudioEngineNative();
        }
        <span class="kwrd">else</span>
        {
            <span class="kwrd">this</span>.audioEngine = <span class="kwrd">new</span> AudioEngineManaged();
        }
    }

    <span class="kwrd">public</span> <span class="kwrd">void</span> Play(<span class="kwrd">string</span> filename)
    {
        <span class="kwrd">this</span>.audioEngine.Play(filename);
    }
}</pre>
<p>Now â€“ the warning:</p>
<p>This approach works, but I would be very hesitant to use it in public facing production code, especially for anything other than initializing your own application.&#160; While this should work in a library, using it has a very nasty side effect: you change the runtime policy of the executing application in a way that is very hidden and non-obvious.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2011/09/15/setting-uselegacyv2runtimeactivationpolicy-at-runtime/feed/</wfw:commentRss>
			<slash:comments>38</slash:comments>
		
		
			</item>
		<item>
		<title>Performance and Optimization Isn&#8217;t Evil</title>
		<link>http://reedcopsey.com/2011/09/09/performance-and-optimization-isnt-evil/</link>
					<comments>http://reedcopsey.com/2011/09/09/performance-and-optimization-isnt-evil/#comments</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Sat, 10 Sep 2011 00:51:00 +0000</pubDate>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[Optimization]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/2011/09/09/performance-and-optimization-isnt-evil/</guid>

					<description><![CDATA[Donald Knuth is a fairly amazing guy.&#160; I consider him one of the most influential contributors to computer science of all time.&#160; Unfortunately, most of the time I hear his name, I cringe.&#160; This is because itâ€™s typically somebody quoting a small portion of one of his famous statements on optimization: â€œpremature optimization is the [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><a href="http://en.wikipedia.org/wiki/Donald_Knuth">Donald Knuth</a> is a fairly amazing guy.&#160; I consider him one of the most influential contributors to computer science of all time.&#160; Unfortunately, most of the time I hear his name, I cringe.&#160; This is because itâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s typically somebody quoting a small <em>portion</em> of one of his famous statements on optimization: â€œ<em>premature optimization is the root of all evil.</em>â€</p>
<p> I mention that this is only a <em>portion of the entire quote</em>, and, as such, I feel that Knuth is being quoted out of context.&#160; Optimization is important.&#160; It is a critical part of every software development effort, and should never be ignored.&#160; A developer who ignores optimization is not a professional.&#160; Every developer should understand optimization â€“ know what to optimize, when to optimize it, and how to think about code in a way that is intelligent and productive from day one.<span id="more-311"></span></p>
<p align="left">I want to start by discussing my own, personal motivation here.&#160; I recently <a href="http://reedcopsey.com/2011/08/11/c-performance-pitfall-interop-scenarios-change-the-rules/">wrote about a performance issue I ran across</a>, and was slammed by multiple comments and emails that effectively boiled down to: â€œYouâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />re an idiot.&#160; Premature optimization is the root of all evil.&#160; This doesnâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t matter.â€&#160; It didnâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t matter that I discovered this <em>while measuring in a profiler</em>, and that it was a portion of my code base that can take â€œmany hours to complete.â€&#160; Even so, multiple people instantly jump to â€œitâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s premature â€“ it doesnâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t matter.â€</p>
<p>This is a common thread I see.&#160; For example, StackOverflow has <a href="http://stackoverflow.com/search?q=%22premature+optimization%22">many pages of posts</a> with answers that boil down to (mis)quoting Knuth.&#160; In fact, just about any question relating to a performance related issue gets this quote thrown at it immediately â€“ whether it deserves it or not.&#160; </p>
<p>That being said, I did receive some positive comments and emails as well.&#160; Many people want to understand how to optimize their code, approaches to take, tools and techniques they can use, and any other advice they can discover.</p>
<p>First, lets get back to Knuth â€“ I mentioned before that Knuth is being quoted out of context.&#160; Lets start by looking at the entire quote from his 1974 paper <a href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.103.6084&amp;rep=rep1&amp;type=pdf">Structured Programming with go to Statements</a>:</p>
<p>â€œ<i>We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%. A good programmer will not be lulled into complacency by such reasoning, he will be wise to look carefully at the critical code; but only after that code has been identified.â€</i></p>
<p>Ironically, if you read Knuthâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s original paper, this statement was made in the middle of a discussion of how Knuth himself had changed how he approaches optimization.&#160; It was never a statement saying â€œdonâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t optimizeâ€, but rather, â€œoptimizing intelligently provides huge advantages.â€&#160; His approach had three benefits: â€œ<em>a) it doesnâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t take long</em>â€ â€¦ <em>â€œb) the payoff is realâ€, </em>c) you can â€œ<em>be less efficient in the other parts of my programs, which therefore are more readable and more easily written and debugged.â€</em></p>
<p>Looking at Knuthâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s premise here, and reading that section of his paper, really leads to a few observations:</p>
<ul>
<li>Optimization is important&#160; <em>â€œhe will be wise to look carefully at the critical codeâ€</em></li>
<li>Normally, 3% of your code â€“ three lines out of every 100 you write, are â€œ<em>critical codeâ€ </em>and will require some optimization: <em>â€œwe should not pass up our opportunities in that critical 3%â€</em></li>
<li>Optimization, if done well, should not be time consuming: â€œ<em>it doesnâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t take long</em>â€</li>
<li>Optimization, if done correctly, provides real benefits: <em>â€œthe payoff is realâ€</em></li>
</ul>
<p align="left">None of this is new information.&#160; People who care about optimization have been discussing this for years â€“ for example, Rico Marianiâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s <a href="http://blogs.msdn.com/b/ricom/archive/2003/12/12/43245.aspx">Designing For Performance</a> (a fantastic article) discusses many of the same issues very intelligently.</p>
<p align="left">That being said, many developers seem unable or unwilling to consider optimization.&#160; Many others donâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t seem to know where to start.&#160; As such, Iâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />m going to spend some time writing about optimization â€“ what is it, how should we think about it, and what can we do to improve our own code.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2011/09/09/performance-and-optimization-isnt-evil/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title>C# Performance Pitfall &#8211; Interop Scenarios Change the Rules</title>
		<link>http://reedcopsey.com/2011/08/11/c-performance-pitfall-interop-scenarios-change-the-rules/</link>
					<comments>http://reedcopsey.com/2011/08/11/c-performance-pitfall-interop-scenarios-change-the-rules/#comments</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Thu, 11 Aug 2011 19:30:52 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Performance]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/2011/08/11/c-performance-pitfall-interop-scenarios-change-the-rules/</guid>

					<description><![CDATA[C# and .NET, overall, really do have fantastic performance in my opinion.&#160; That being said, the performance characteristics dramatically differ from native programming, and take some relearning if youâ€™re used to doing performance optimization in most other languages, especially C, C++, and similar.&#160; However, there are times when revisiting tricks learned in native code play [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>C# and .NET, overall, really do have fantastic performance in my opinion.&#160; That being said, the performance characteristics dramatically differ from native programming, and take some relearning if youâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />re used to doing performance optimization in most other languages, especially C, C++, and similar.&#160; However, there are times when revisiting tricks learned in native code play a critical role in performance optimization in C#.</p>
<p>I recently ran across a nasty scenario that illustrated to me how dangerous following any fixed rules for optimization can beâ€¦</p>
<p><span id="more-310"></span></p>
<p>The rules in C# when optimizing code are very different than C or C++.&#160; Often, theyâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />re exactly backwards.&#160; For example, in C and C++, lifting a variable out of loops in order to avoid memory allocations often can have huge advantages.&#160; If some function within a call graph is allocating memory dynamically, and that gets called in a loop, it can dramatically slow down a routine.</p>
<p>This can be a tricky bottleneck to track down, even with a profiler.&#160; Looking at the memory allocation graph is usually the key for spotting this routine, as itâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s often â€œhiddenâ€ deep in call graph.&#160; For example, while optimizing some of my scientific routines, I ran into a situation where I had a loop similar to:</p>
<pre class="csharpcode"><span class="kwrd">for</span> (i=0; i&lt;numberToProcess; ++i)
{
   <span class="rem">// Do some work</span>
   ProcessElement(element[i]);
}</pre>
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>This loop was at a fairly high level in the call graph, and often could take many <em>hours</em> to complete, depending on the input data.&#160; As such, any performance optimization we could achieve would be greatly appreciated by our users.</p>
<p>After a fair bit of profiling, I noticed that a couple of function calls down the call graph (inside of ProcessElement), there was some code that effectively was doing:</p>
<pre class="csharpcode"><span class="rem">// Allocate some data required</span>
DataStructure* data = <span class="kwrd">new</span> DataStructure(num);
<span class="rem">// Call into a subroutine that passed around and manipulated this data highly</span>
CallSubroutine(data);
<span class="rem">// Read and use some values from here</span>
<span class="kwrd">double</span> values = data-&gt;Foo;
<span class="rem">// Cleanup </span>
<span class="kwrd">delete</span> data;
<span class="rem">// ...</span>
<span class="kwrd">return</span> bar;</pre>
<p>Normally, if â€œDataStructureâ€ was a simple data type, I could just allocate it on the stack.&#160; However, itâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s constructor, internally, allocated itâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s own memory using new, so this wouldnâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t eliminate the problem.&#160; In this case, however, I could change the call signatures to allow the pointer to the data structure to be passed into ProcessElement and through the call graph, allowing the inner routine to <em>reuse</em> the same â€œdataâ€ memory instead of allocating.&#160; At the highest level, my code effectively changed to something like:</p>
<pre class="csharpcode">DataStructure* data = <span class="kwrd">new</span> DataStructure(numberToProcess);
<span class="kwrd">for</span> (i=0; i&lt;numberToProcess; ++i)
{
   <span class="rem">// Do some work</span>
   ProcessElement(element[i], data);
}
delete data;</pre>
<p>Granted, this dramatically reduced the maintainability of the code, so it wasnâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t something I wanted to do unless there was a significant benefit.&#160; In this case, after profiling the new version, I found that it increased the overall performance dramatically â€“ my main test case went from 35 minutes runtime down to 21 minutes.&#160; This was such a significant improvement, I felt it was worth the reduction in maintainability.</p>
<p>In C and C++, itâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s generally a good idea (for performance) to:</p>
<ul>
<li>Reduce the number of memory allocations as much as possible, </li>
<li>Use fewer, larger memory allocations instead of many smaller ones, and </li>
<li>Allocate as high up the call stack as possible, and reuse memory </li>
</ul>
<p>Iâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />ve seen many people try to make similar optimizations in C# code.&#160; For good or bad, this is typically <strong>not a good idea</strong>.&#160; The garbage collector in .NET completely changes the rules here.</p>
<p>In C#, reallocating memory in a loop is not always a bad idea.&#160; In this scenario, for example, I may have been much better off leaving the original code alone.&#160; The reason for this is the garbage collector.&#160; The GC in .NET is incredibly effective, and leaving the allocation deep inside the call stack has some huge advantages.&#160; First and foremost, it tends to make the code more maintainable â€“ passing around object references tends to couple the methods together more than necessary, and overall increase the complexity of the code.&#160; This is something that should be avoided unless there is a significant reason.&#160; Second, (unlike C and C++) memory allocation of a single object in C# is normally cheap and fast.&#160; Finally, and most critically, there is a large advantage to having short lived objects.&#160; If you lift a variable out of the loop and reuse the memory, its much more likely that object will get promoted to Gen1 (or worse, Gen2).&#160; This can cause expensive compaction operations to be required, and also lead to (at least temporary) memory fragmentation as well as more costly collections later.</p>
<p>As such, Iâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />ve found that itâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s often (though not always) faster to leave memory allocations where youâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />d naturally place them â€“ deep inside of the call graph, inside of the loops.&#160; This causes the objects to stay very short lived, which in turn increases the efficiency of the garbage collector, and can dramatically improve the overall performance of the routine as a whole.</p>
<p>In C#, I tend to:</p>
<ul>
<li>Keep variable declarations in the tightest scope possible</li>
<li>Declare and allocate objects at usage</li>
</ul>
<p>While this tends to cause some of the same goals (reducing unnecessary allocations, etc), the goal here is a bit different â€“ itâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s about keeping the objects rooted for as little time as possible in order to (attempt) to keep them completely in Gen0, or worst case, Gen1.&#160; It also has the huge advantage of keeping the code very maintainable â€“ objects are used and â€œreleasedâ€ as soon as possible, which keeps the code very clean.&#160; It does, however, often have the side effect of causing more allocations to occur, but keeping the objects rooted for a much shorter time.</p>
<p>Now â€“ nowhere here am I suggesting that these rules are hard, fast rules that are always true.&#160; That being said, my time spent optimizing over the years encourages me to naturally write code that follows the above guidelines, then profile and adjust as necessary.&#160; In my current project, however, I ran across one of those nasty little pitfalls thatâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s something to keep in mind â€“ interop changes the rules.</p>
<p>In this case, I was dealing with an API that, internally, used some COM objects.&#160; In this case, these COM objects were leading to native allocations (most likely C++) occurring in a loop deep in my call graph.&#160; Even though I was writing nice, clean managed code, the normal managed code rules for performance no longer apply.&#160; </p>
<p>After profiling to find the bottleneck in my code, I realized that my inner loop, a innocuous looking block of C# code, was effectively causing a set of native memory allocations in every iteration.&#160; This required going back to a â€œnative programmingâ€ mindset for optimization.&#160; Lifting these variables and reusing them took a 1:10 routine down to 0:20 â€“ again, a very worthwhile improvement.</p>
<p>Overall, the lessons here are:</p>
<ul>
<li>Always profile if you suspect a performance problem â€“ donâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t assume any rule is correct, or any code is efficient just because it looks like it should be</li>
<li>Remember to check memory allocations when profiling, not just CPU cycles</li>
<li>Interop scenarios often cause managed code to act very differently than â€œnormalâ€ managed code.</li>
<li>Native code can be hidden very cleverly inside of managed wrappers</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2011/08/11/c-performance-pitfall-interop-scenarios-change-the-rules/feed/</wfw:commentRss>
			<slash:comments>9</slash:comments>
		
		
			</item>
		<item>
		<title>Async CTP Refresh for Visual Studio 2010 SP1 Released</title>
		<link>http://reedcopsey.com/2011/04/13/async-ctp-refresh-for-visual-studio-2010-sp1-released/</link>
					<comments>http://reedcopsey.com/2011/04/13/async-ctp-refresh-for-visual-studio-2010-sp1-released/#respond</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Wed, 13 Apr 2011 16:30:29 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Async]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[.NET 4]]></category>
		<category><![CDATA[C# 4]]></category>
		<category><![CDATA[C# 5]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/2011/04/13/async-ctp-refresh-for-visual-studio-2010-sp1-released/</guid>

					<description><![CDATA[The Visual Studio team today released an update to the Visual Studio Async CTP which allows it to be used with Visual Studio SP1.&#160; This new CTP includes some very nice new additions over the previous CTP.&#160; The main highlights of this release include: Compatibility with Visual Studio SP1 APIs for Windows Phone 7 Compatibility [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>The Visual Studio team today released an <a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=4738205d-5682-47bf-b62e-641f6441735b&amp;displaylang=en">update to the Visual Studio Async CTP</a> which allows it to be used with Visual Studio SP1.&#160; This new CTP includes some very nice new additions over the previous CTP.&#160; The main highlights of this release include:</p>
<ul>
<li>Compatibility with Visual Studio SP1</li>
<li>APIs for Windows Phone 7</li>
<li>Compatibility with non-English installations</li>
<li>Compatibility with Visual Studio Express Edition</li>
<li>More efficient Async methods due to a change in the API</li>
<li>Numerous bug fixes</li>
<li>New EULA which allows distribution in production environments</li>
<p> Anybody using the Async CTP should consider upgrading to the new version immediately.&#160; For details, visit the <a href="http://msdn.microsoft.com/en-us/vstudio/gg316360">Visual Studio Asynchronous Programming</a> page on MSDN.</ul>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2011/04/13/async-ctp-refresh-for-visual-studio-2010-sp1-released/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>ConcurrentDictionary&#060;TKey,TValue&#062; used with Lazy&#060;T&#062;</title>
		<link>http://reedcopsey.com/2011/01/16/concurrentdictionarytkeytvalue-used-with-lazyt/</link>
					<comments>http://reedcopsey.com/2011/01/16/concurrentdictionarytkeytvalue-used-with-lazyt/#comments</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Sun, 16 Jan 2011 21:04:03 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Parallelism]]></category>
		<category><![CDATA[.NET 4]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/2011/01/16/concurrentdictionarytkeytvalue-used-with-lazyt/</guid>

					<description><![CDATA[In a recent thread on the MSDN forum for the TPL, Stephen Toub suggested mixing ConcurrentDictionary&#60;T,U&#62; with Lazy&#60;T&#62;.&#160; This provides a fantastic model for creating a thread safe dictionary of values where the construction of the value type is expensive.&#160; This is an incredibly useful pattern for many operations, such as value caches. The ConcurrentDictionary&#60;TKey, [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>In a <a href="http://social.msdn.microsoft.com/Forums/en-US/parallelextensions/thread/e350f7d0-b860-482e-9b84-8dba12267d25">recent thread</a> on the <a href="http://social.msdn.microsoft.com/Forums/en-US/parallelextensions/threads">MSDN forum for the TPL</a>, Stephen Toub suggested mixing ConcurrentDictionary&lt;T,U&gt; with Lazy&lt;T&gt;.&#160; This provides a fantastic model for creating a thread safe dictionary of values where the construction of the value type is expensive.&#160; This is an incredibly useful pattern for many operations, such as value caches.</p>
<p>  <span id="more-295"></span>  </p>
<p>The <a href="http://msdn.microsoft.com/en-us/library/dd287191.aspx">ConcurrentDictionary&lt;TKey, TValue&gt; class</a> was added in .NET 4, and provides a thread-safe, lock free collection of key value pairs.&#160; While this is a fantastic replacement for Dictionary&lt;TKey, TValue&gt;, it has a potential flaw when used with values where construction of the value class is expensive.</p>
<p>The typical way this is used is to call a method such as <a href="http://msdn.microsoft.com/en-us/library/ee378677.aspx">GetOrAdd</a> to fetch or add a value to the dictionary.&#160; It handles all of the thread safety for you, but as a result, if two threads call this simultaneously, two instances of TValue can easily be constructed.</p>
<p>If TValue is very expensive to construct, or worse, has side effects if constructed too often, this is less than desirable.&#160; While you can easily work around this with locking, Stephen Toub provided a very clever alternative â€“ using Lazy&lt;TValue&gt; as the value in the dictionary instead.</p>
<p>This looks like the following.&#160; Instead of calling:</p>
<pre class="csharpcode">MyValue <span class="kwrd">value</span> = dictionary.GetOrAdd(
                             key, 
                             () =&gt; <span class="kwrd">new</span> MyValue(key));</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>We would instead use a ConcurrentDictionary&lt;TKey, Lazy&lt;TValue&gt;&gt;, and write:</p>
<pre class="csharpcode">MyValue <span class="kwrd">value</span> = dictionary.GetOrAdd(
                             key, 
                             () =&gt; <span class="kwrd">new</span> Lazy&lt;MyValue&gt;(
                                 () =&gt; <span class="kwrd">new</span> MyValue(key)))
                          .Value;</pre>
<p>This simple change dramatically changes how the operation works.&#160; Now, if two threads call this simultaneously, instead of constructing two MyValue instances, we construct two Lazy&lt;MyValue&gt; instances.</p>
<p>However, the Lazy&lt;T&gt; class is very cheap to construct.&#160; Unlike â€œMyValueâ€, we can safely afford to construct this twice and â€œthrow awayâ€ one of the instances.</p>
<p>We then call Lazy&lt;T&gt;.Value at the end to fetch our â€œMyValueâ€ instance.&#160; At this point, GetOrAdd will always return the same instance of Lazy&lt;MyValue&gt;.&#160; Since Lazy&lt;T&gt; doesnâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t construct the MyValue instance until requested, the actual MyClass instance returned is only constructed once.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2011/01/16/concurrentdictionarytkeytvalue-used-with-lazyt/feed/</wfw:commentRss>
			<slash:comments>16</slash:comments>
		
		
			</item>
		<item>
		<title>C# 5 Async, Part 3: Preparing Existing code For Await</title>
		<link>http://reedcopsey.com/2010/12/14/c-5-async-part-3-preparing-existing-code-for-await/</link>
					<comments>http://reedcopsey.com/2010/12/14/c-5-async-part-3-preparing-existing-code-for-await/#comments</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Tue, 14 Dec 2010 18:25:00 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Async]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[.NET 4.5]]></category>
		<category><![CDATA[C# 5]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/2010/12/14/c-5-async-part-3-preparing-existing-code-for-await/</guid>

					<description><![CDATA[While the Visual Studio Async CTP provides a fantastic model for asynchronous programming, it requires code to be implemented in terms of Task and Task&#60;T&#62;.&#160; The CTP adds support for Task-based asynchrony to the .NET Framework methods, and promises to have these implemented directly in the framework in the future.&#160; However, existing code outside the [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>While the <a href="http://msdn.microsoft.com/en-gb/vstudio/async.aspx" target="_blank">Visual Studio Async CTP</a> provides a fantastic model for asynchronous programming, it requires code to be implemented in terms of <a href="http://msdn.microsoft.com/en-us/library/dd537609.aspx">Task and Task&lt;T&gt;</a>.&#160; The CTP adds support for Task-based asynchrony to the .NET Framework methods, and promises to have these implemented directly in the framework in the future.&#160; However, existing code outside the framework will need to be converted to using the Task class prior to being usable via the CTP.</p>
<p>  <span id="more-292"></span> Wrapping existing asynchronous code into a Task or Task&lt;T&gt; is, thankfully, fairly straightforward.&#160; There are two main approaches to this.    </p>
<p>Code written using the <a href="http://msdn.microsoft.com/en-us/library/ms228963.aspx">Asynchronous Programming Model</a> (APM) is very easy to convert to using Task&lt;T&gt;.&#160; The <a href="http://msdn.microsoft.com/en-us/library/dd321401.aspx">TaskFactory class</a> provides the tools to directly convert APM code into a method returning a Task&lt;T&gt;.&#160; This is done via the <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory.fromasync.aspx">FromAsync method</a>.&#160; This method takes the BeginOperation and EndOperation methods, as well as any parameters and state objects as arguments, and returns a Task&lt;T&gt; directly.</p>
<p>For example, we could easily convert the WebRequest BeginGetResponse and EndGetResponse methods into a method which returns a Task&lt;WebResponse&gt; via:</p>
<pre class="csharpcode">Task&lt;WebResponse&gt; task = Task.Factory
                             .FromAsync&lt;WebResponse&gt;(
                                 request.BeginGetResponse,
                                 request.EndGetResponse,
                                 <span class="kwrd">null</span>);</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p><!--.csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } --><a href="http://msdn.microsoft.com/en-us/library/wewwczdw.aspx">Event-based Asynchronous Pattern</a> (EAP) code can also be wrapped into a Task&lt;T&gt;, though this requires a bit more effort than the one line of code above.&#160; This is handled via the <a href="http://msdn.microsoft.com/en-us/library/dd449174.aspx">TaskCompletionSource&lt;T&gt; class</a>.&#160; MSDN provides a detailed <a href="http://msdn.microsoft.com/en-us/library/ee622454.aspx">example of using this to wrap an EAP operation into a method returning Task&lt;T&gt;</a>.&#160; It demonstrates handling cancellation and exception handling as well as the basic operation of the asynchronous method itself.</p>
<p>The basic form of this operation is typically:</p>
<pre class="csharpcode">Task&lt;YourResult&gt; GetResultAsync()
{
    var tcs = <span class="kwrd">new</span> TaskCompletionSource&lt;YourResult&gt;();
    <span class="rem">// Handle the event, and setup the task results...</span>
    <span class="kwrd">this</span>.GetResultCompleted += (o,e) =&gt;
    {
       <span class="kwrd">if</span> (e.Error != <span class="kwrd">null</span>)
            tcs.TrySetException(e.Error);
       <span class="kwrd">else</span> <span class="kwrd">if</span> (e.Cancelled)
            tcs.TrySetCanceled();
       <span class="kwrd">else</span>
            tcs.TrySetResult(e.Result);
    };

    <span class="rem">// Call the EAP-based asynchronous method</span>
    <span class="kwrd">this</span>.GetResult();

    <span class="rem">// Return the task from the TaskCompletionSource</span>
    <span class="kwrd">return</span> tcs.Task;
}</pre>
<p>We can easily use these methods to wrap our own code into a method that returns a Task&lt;T&gt;.&#160; Existing libraries which cannot be edited can be extended via Extension methods.&#160; The CTP uses this technique to add appropriate methods throughout the framework.</p>
<p>The suggested naming for these methods is to define these methods as â€œTask&lt;YourResult&gt; YourClass.YourOperation<strong>Async</strong>(â€¦)â€.&#160; However, this naming often conflicts with the default naming of the EAP.&#160; If this is the case, the CTP has standardized on using â€œTask&lt;YourResult&gt; YourClass.YourOperation<strong>TaskAsync</strong>(â€¦)â€.</p>
<p>Once weâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />ve wrapped all of our existing code into operations that return Task&lt;T&gt;, we can begin investigating how the Async CTP can be used with our own code.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2010/12/14/c-5-async-part-3-preparing-existing-code-for-await/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>C# 5 Async, Part 2: Asynchrony Today</title>
		<link>http://reedcopsey.com/2010/12/02/c-5-async-part-2-asynchrony-today/</link>
					<comments>http://reedcopsey.com/2010/12/02/c-5-async-part-2-asynchrony-today/#respond</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Thu, 02 Dec 2010 23:44:00 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Async]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[.NET 4.5]]></category>
		<category><![CDATA[C# 5]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/2010/12/02/c-5-async-part-2-asynchrony-today/</guid>

					<description><![CDATA[The .NET Framework has always supported asynchronous operations.&#160; However, different mechanisms for supporting exist throughout the framework.&#160; While there are at least three separate asynchronous patterns used through the framework, only the latest is directly usable with the new Visual Studio Async CTP.&#160; Before delving into details on the new features, I will talk about [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>The .NET Framework has always supported asynchronous operations.&#160; However, different mechanisms for supporting exist throughout the framework.&#160; While there are at least three separate asynchronous patterns used through the framework, only the latest is directly usable with the new <a href="http://msdn.microsoft.com/en-gb/vstudio/async.aspx" target="_blank">Visual Studio Async CTP</a>.&#160; Before delving into details on the new features, I will talk about existing asynchronous code, and demonstrate how to adapt it for use with the new pattern.</p>
<p>  <span id="more-291"></span>  </p>
<p align="left">The first asynchronous pattern used in the .NET framework was the <a href="http://msdn.microsoft.com/en-us/library/ms228963.aspx">Asynchronous Programming Model</a> (APM).&#160; This pattern was based around <a href="http://en.wikipedia.org/wiki/Callback_(computer_science)">callbacks</a>.&#160; A method is used to start the operation.&#160; It typically is named as <strong>Begin</strong>SomeOperation.&#160; This method is passed a callback defined as an <a href="http://msdn.microsoft.com/en-us/library/system.asynccallback.aspx">AsyncCallback</a>, and returns an object that implements <a href="http://msdn.microsoft.com/en-us/library/system.iasyncresult.aspx">IAsyncResult</a>.&#160; Later, the IAsyncResult is used in a call to a method named <strong>End</strong>SomeOperation, which blocks until completion and returns the value normally directly returned from the synchronous version of the operation.&#160; Often, the <strong>End</strong>SomeOperation call would be called from the callback function passed, which allows you to write code that never blocks.</p>
<p align="left">While this pattern works perfectly to prevent blocking, it can make quite confusing code, and be difficult to implement.&#160; For example, the sample code provided for <a href="http://msdn.microsoft.com/en-us/library/7db28s3c.aspx">FileStreamâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s BeginRead/EndRead</a> methods is not simple to understand.&#160; In addition, implementing your own asynchronous methods requires creating an entire class just to implement the IAsyncResult.</p>
<p align="left">Given the complexity of the APM, other options have been introduced in later versions of the framework.&#160; The next major pattern introduced was the <a href="http://msdn.microsoft.com/en-us/library/wewwczdw.aspx">Event-based Asynchronous Pattern</a> (EAP).&#160; This provides a simpler pattern for asynchronous operations.&#160; It works by providing a method typically named SomeOperation<strong>Async</strong>, which signals its completion via an event typically named SomeOperation<strong>Completed</strong>.</p>
<p align="left">The EAP provides a simpler model for asynchronous programming.&#160; It is much easier to understand and use, and far simpler to implement.&#160; Instead of requiring a custom class and callbacks, the standard event mechanism in C# is used directly.&#160; For example, the <a href="http://msdn.microsoft.com/en-us/library/tt0f69eh.aspx">WebClient class</a> uses this extensively.&#160; A method is used, such as <a href="http://msdn.microsoft.com/en-us/library/ms144190.aspx">DownloadDataAsync</a>, and the results are returned via the <a href="http://msdn.microsoft.com/en-us/library/system.net.webclient.downloaddatacompleted.aspx">DownloadDataCompleted</a> event.</p>
<p align="left">While the EAP is far simpler to understand and use than the APM, it is still not ideal.&#160; By separating your code into method calls and event handlers, the logic of your program gets more complex.&#160; It also typically loses the ability to block until the result is received, which is often useful.&#160; Blocking often requires writing the code to block by hand, which is error prone and adds complexity.</p>
<p align="left">As a result, .NET 4 introduced a third major pattern for asynchronous programming.&#160; The <a href="http://reedcopsey.com/2010/03/15/parallelism-in-net-part-13-introducing-the-task-class/">Task&lt;T&gt; class</a> introduced a new, simpler concept for asynchrony.&#160; Task and Task&lt;T&gt; effectively represent an operation that will complete at some point in the future.&#160; This is a perfect model for thinking about asynchronous code, and is the preferred model for all new code going forward.&#160; Task and Task&lt;T&gt; provide all of the advantages of both the APM and the EAP models â€“ you have the ability to block on results (via Task.Wait() or Task&lt;T&gt;.Result), and you can stay completely asynchronous via the use of <a href="http://reedcopsey.com/2010/04/19/parallelism-in-net-part-17-think-continuations-not-callbacks/">Task Continuations</a>.&#160; In addition, the Task class provides a new model for <a href="http://reedcopsey.com/2010/07/19/parallelism-in-net-part-18-task-continuations-with-multiple-tasks/">task composition</a> and <a href="http://reedcopsey.com/2010/10/26/parallelism-in-net-part-19-taskcontinuationoptions/">error and cancelation handling</a>.&#160; This is a far superior option to the previous asynchronous patterns.</p>
<p align="left">The <a href="http://msdn.microsoft.com/en-gb/vstudio/async.aspx" target="_blank">Visual Studio Async CTP</a> extends the Task based asynchronous model, allowing it to be used in a much simpler manner.&#160; However, it requires the use of Task and Task&lt;T&gt; for all operations.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2010/12/02/c-5-async-part-2-asynchrony-today/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>C# 5 Async, Part 1: Simplifying Asynchrony &#8211; That for which we await</title>
		<link>http://reedcopsey.com/2010/10/28/c-5-async-part-1-simplifying-asynchrony-that-for-which-we-await/</link>
					<comments>http://reedcopsey.com/2010/10/28/c-5-async-part-1-simplifying-asynchrony-that-for-which-we-await/#comments</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Thu, 28 Oct 2010 18:46:47 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Async]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[.NET 4.5]]></category>
		<category><![CDATA[C# 5]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/2010/10/28/c-5-async-part-1-simplifying-asynchrony-that-for-which-we-await/</guid>

					<description><![CDATA[Todayâ€™s announcement at PDC of the future directions C# is taking excite me greatly.Â  The new Visual Studio Async CTP is amazing.Â  Asynchronous code â€“ code which frustrates and demoralizes even the most advanced of developers, is taking a huge leap forward in terms of usability.Â  This is handled by building on the Task functionality [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Todayâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s announcement at PDC of the future directions C# is taking excite me greatly.Â  The new <a href="http://msdn.microsoft.com/en-gb/vstudio/async.aspx" target="_blank">Visual Studio Async CTP</a> is amazing.Â  Asynchronous code â€“ code which frustrates and demoralizes even the most advanced of developers, is taking a huge leap forward in terms of usability.Â  This is handled by building on the <a href="http://reedcopsey.com/2010/03/15/parallelism-in-net-part-13-introducing-the-task-class/" target="_blank">Task</a> functionality in .NET 4, as well as the addition of two new keywords being added to the C# language: <strong>async </strong>and <strong>await</strong>.</p>
<p><span id="more-289"></span></p>
<p align="left">This core of the new asynchronous functionality is built upon three key features.Â  First is the <a href="http://reedcopsey.com/2010/03/15/parallelism-in-net-part-13-introducing-the-task-class/" target="_blank">Task functionality</a> in .NET 4, and based on <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx" target="_blank">Task</a> and <a href="http://msdn.microsoft.com/en-us/library/dd321424.aspx" target="_blank">Task&lt;TResult&gt;</a>.Â  While Task was intended to be the <a href="http://msdn.microsoft.com/en-us/library/dd537609.aspx" target="_blank">primary means of asynchronous programming</a> with .NET 4, the .NET Framework was still based mainly on the <a href="http://msdn.microsoft.com/en-us/library/ms228969.aspx" target="_blank">Asynchronous Pattern and the Event-based Asynchronous Pattern</a>.</p>
<p align="left">The .NET Framework added functionality and guidance for <a href="http://msdn.microsoft.com/en-us/library/dd997405.aspx" target="_blank">wrapping existing APIs into a Task based API</a>, but the framework itself didnâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t really adopt Task or Task&lt;TResult&gt; in any meaningful way.Â  The CTP shows that, going forward, this is changing.</p>
<p align="left">One of the three key new features coming in C# is actually a .NET Framework feature.Â  Nearly every asynchronous API in the .NET Framework has been wrapped into a new, Task-based method calls.Â  In the CTP, this is done via as external assembly (<em>AsyncCtpLibrary.dll</em>) which uses Extension Methods to wrap the existing APIs.Â  However, going forward, this will be handled directly within the Framework.Â  This will have a unifying effect throughout the .NET Framework.Â  This is the first building block of the new features for asynchronous programming:</p>
<p align="left"><strong>Going forward, all asynchronous operations will work via a method that returns Task or Task&lt;TResult&gt;</strong></p>
<p align="left">The second key feature is the new <strong>async</strong> contextual keyword being added to the language.Â  The <strong>async </strong>keyword is used to declare an <em>asynchronous function</em>, which is a method that either returns void, a Task, or a Task&lt;T&gt;.</p>
<p>Inside the asynchronous function, there must be at least one <strong>await </strong>expression.Â  This is a new C# keyword (<strong>await</strong>) that is used to automatically take a series of statements and break it up to potentially use discontinuous evaluation.Â  This is done by using <strong>await </strong>on any expression that evaluates to a <strong>Task</strong> or <strong>Task&lt;T&gt;</strong>.</p>
<p>For example, suppose we want to download a webpage as a string.Â  There is a new method added to <a href="http://msdn.microsoft.com/en-us/library/system.net.webclient.aspx" target="_blank">WebClient</a>: Task&lt;string&gt; WebClient.DownloadStringTaskAsync(Uri).Â  Since this returns a Task&lt;string&gt; we can use it within an asynchronous function.Â  Suppose, for example, that we wanted to do something similar to <a href="http://reedcopsey.com/2010/10/27/parallelism-in-net-part-20-using-task-with-existing-apis/" target="_blank">my asynchronous Task example</a> â€“ download a web page asynchronously and check to see if it supports XHTML 1.0, then report this into a TextBox.Â  This could be done like so:</p>
<pre class="csharpcode"><span class="kwrd">private</span> async <span class="kwrd">void</span> button1_Click(<span class="kwrd">object</span> sender, RoutedEventArgs e)
{
    <span class="kwrd">string</span> url = <span class="str">"http://reedcopsey.com"</span>;
    <span class="kwrd">string</span> content = await <span class="kwrd">new</span> WebClient().DownloadStringTaskAsync(url);
    <span class="kwrd">this</span>.textBox1.Text = <span class="kwrd">string</span>.Format(<span class="str">"Page {0} supports XHTML 1.0: {1}"</span>,
      url, content.Contains(<span class="str">"XHTML 1.0"</span>));
}</pre>
<p>Letâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s walk through whatâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s happening here, step by step.Â  By adding the <strong>async </strong>contextual keyword to the method definition, we are able to use the <strong>await </strong>keyword on our WebClient.DownloadStringTaskAsync method call.</p>
<p>When the user clicks this button, the new method (Task&lt;string&gt; WebClient.DownloadStringTaskAsync(string)) is called, which returns a Task&lt;string&gt;.Â  By adding the <strong>await</strong> keyword, the runtime will call this method that returns Task&lt;string&gt;, and execution will return to the caller at this point.Â  This means that our <strong>UI is not blocked while the webpage is downloaded.</strong>Â  Instead, the UI thread will â€œawaitâ€ at this point, and let the WebClient do itâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s thing asynchronously.</p>
<p>When the WebClient finishes downloading the string, the user interfaceâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s synchronization context will automatically be used to â€œpick upâ€ where it left off, and the Task&lt;string&gt; returned from DownloadStringTaskAsync is automatically unwrapped and set into the content variable.Â  At this point, we can use that and set our text box content.</p>
<p>There are a couple of key points here:</p>
<p><strong>Asynchronous functions are declared with the <em>async </em>keyword, and contain one or more <em>await </em>expressions</strong></p>
<p>In addition to the obvious benefits of shorter, simpler code â€“ there are some subtle but tremendous benefits in this approach.Â  When the execution of this asynchronous function continues after the first await statement, the initial synchronization context is used to continue the execution of this function.Â  That means that <strong>we donâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t have to explicitly marshal the call that sets textbox1.Text back to the UI thread â€“ </strong>itâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s handled automatically by the language and framework!Â  Exception handling around asynchronous method calls also just works.</p>
<p>Iâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />d recommend every C# developer take a look at the documentation on the new <a href="http://msdn.microsoft.com/en-gb/vstudio/async.aspx" target="_blank">Asynchronous Programming for C# and Visual Basic</a> page, download the <a href="http://go.microsoft.com/fwlink/?LinkId=203690" target="_blank">Visual Studio Async CTP</a>, and try it out.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2010/10/28/c-5-async-part-1-simplifying-asynchrony-that-for-which-we-await/feed/</wfw:commentRss>
			<slash:comments>19</slash:comments>
		
		
			</item>
		<item>
		<title>Parallelism in .NET &#8211; Part 20, Using Task with Existing APIs</title>
		<link>http://reedcopsey.com/2010/10/27/parallelism-in-net-part-20-using-task-with-existing-apis/</link>
					<comments>http://reedcopsey.com/2010/10/27/parallelism-in-net-part-20-using-task-with-existing-apis/#comments</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Wed, 27 Oct 2010 20:15:31 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Parallelism]]></category>
		<category><![CDATA[.NET 4]]></category>
		<category><![CDATA[C# 4]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/2010/10/27/parallelism-in-net-part-20-using-task-with-existing-apis/</guid>

					<description><![CDATA[Although the Task class provides a huge amount of flexibility for handling asynchronous actions, the .NET Framework still contains a large number of APIs that are based on the previous asynchronous programming model.&#160; While Task and Task&#60;T&#62; provide a much nicer syntax as well as extending the flexibility, allowing features such as continuations based on [&#8230;]]]></description>
										<content:encoded><![CDATA[<p align="left">Although the <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx">Task class</a> provides a huge amount of flexibility for handling asynchronous actions, the .NET Framework still contains a large number of APIs that are based on the previous <a href="http://msdn.microsoft.com/en-us/library/ms228963.aspx">asynchronous programming model</a>.&#160; While Task and Task&lt;T&gt; provide a much nicer syntax as well as extending the flexibility, allowing features such as <a href="http://reedcopsey.com/2010/07/19/parallelism-in-net-part-18-task-continuations-with-multiple-tasks/">continuations based on multiple tasks</a>, the existing APIs donâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t directly support this workflow. </p>
<p>  <span id="more-288"></span>  </p>
<p align="left">There is a method in the <a href="http://msdn.microsoft.com/en-us/library/dd321401.aspx">TaskFactory class</a> which can be used to adapt the existing APIs to the new Task class: <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory.fromasync(v=VS.100).aspx">TaskFactory.FromAsync</a>.&#160; This method provides a way to convert from the BeginOperation/EndOperation method pair syntax common through .NET Framework directly to a Task&lt;T&gt; containing the results of the operation in the taskâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s Result parameter.</p>
<p align="left">While this method does exist, it unfortunately comes at a cost â€“ the method overloads are far from simple to decipher, and the resulting code is not always as easily understood as newer code based directly on the Task class.&#160; For example, a single call to handle WebRequest.BeginGetResponse/EndGetReponse, one of the easiest â€œpairsâ€ of methods to use, looks like the following:</p>
<pre class="csharpcode">var task = Task.Factory.FromAsync&lt;WebResponse&gt;(
                            request.BeginGetResponse,
                            request.EndGetResponse,
                            <span class="kwrd">null</span>);</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>The compiler is unfortunately unable to infer the correct type, and, as a result, the WebReponse must be explicitly mentioned in the method call.&#160; As a result, I typically recommend wrapping this into an extension method to ease use.&#160; For example, I would place the above in an extension method like:</p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">class</span> WebRequestExtensions
{
    <span class="kwrd">public</span> <span class="kwrd">static</span> Task&lt;WebResponse&gt; GetReponseAsync(<span class="kwrd">this</span> WebRequest request)
    {
        <span class="kwrd">return</span> Task.Factory.FromAsync&lt;WebResponse&gt;(
                        request.BeginGetResponse,
                        request.EndGetResponse,
                        <span class="kwrd">null</span>);
    }
}</pre>
<p>This dramatically simplifies usage.&#160; For example, if we wanted to asynchronously check to see if this blog supported XHTML 1.0, and report that in a text box to the user, we could do:</p>
<pre class="csharpcode">var webRequest = WebRequest.Create(<span class="str">&quot;http://www.reedcopsey.com&quot;</span>);
webRequest.GetReponseAsync().ContinueWith(t =&gt;
    {
        <span class="kwrd">using</span> (var sr = <span class="kwrd">new</span> StreamReader(t.Result.GetResponseStream()))
        {
            <span class="kwrd">string</span> str = sr.ReadLine();;
            <span class="kwrd">this</span>.textBox1.Text = <span class="kwrd">string</span>.Format(<span class="str">&quot;Page at {0} supports XHTML 1.0: {1}&quot;</span>, 
                t.Result.ResponseUri, 
                str.Contains(<span class="str">&quot;XHTML 1.0&quot;</span>));
        }
    }, TaskScheduler.FromCurrentSynchronizationContext());</pre>
<p>&#160;</p>
<p>By using a continuation with a TaskScheduler based on the current synchronization context, we can keep this request asynchronous, check based on the first line of the response string, and report the results back on our UI directly.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2010/10/27/parallelism-in-net-part-20-using-task-with-existing-apis/feed/</wfw:commentRss>
			<slash:comments>8</slash:comments>
		
		
			</item>
		<item>
		<title>Parallelism in .NET &#8211; Part 19, TaskContinuationOptions</title>
		<link>http://reedcopsey.com/2010/10/26/parallelism-in-net-part-19-taskcontinuationoptions/</link>
					<comments>http://reedcopsey.com/2010/10/26/parallelism-in-net-part-19-taskcontinuationoptions/#comments</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Wed, 27 Oct 2010 00:30:53 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Parallelism]]></category>
		<category><![CDATA[.NET 4]]></category>
		<category><![CDATA[C# 4]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/2010/10/26/parallelism-in-net-part-19-taskcontinuationoptions/</guid>

					<description><![CDATA[My introduction to Task continuations demonstrates continuations on the Task class.&#160; In addition, Iâ€™ve shown how continuations allow handling of multiple tasks in a clean, concise manner.&#160; Continuations can also be used to handle exceptional situations using a clean, simple syntax. In addition to standard Task continuations , the Task class provides some options for [&#8230;]]]></description>
										<content:encoded><![CDATA[<p align="left">My <a href="http://reedcopsey.com/2010/04/19/parallelism-in-net-part-17-think-continuations-not-callbacks/" target="_blank">introduction to Task continuations</a> demonstrates continuations on the <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx" target="_blank">Task class</a>.&#160; In addition, Iâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />ve shown how <a href="http://reedcopsey.com/2010/07/19/parallelism-in-net-part-18-task-continuations-with-multiple-tasks/" target="_blank">continuations allow handling of multiple tasks</a> in a clean, concise manner.&#160; Continuations can also be used to handle exceptional situations using a clean, simple syntax.</p>
<p>  <span id="more-284"></span>  </p>
<p align="left">In addition to standard <a href="http://reedcopsey.com/2010/04/19/parallelism-in-net-part-17-think-continuations-not-callbacks/" target="_blank">Task continuations</a> , the <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx" target="_blank">Task class</a> provides some options for filtering continuations automatically.&#160; This is handled via the <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskcontinuationoptions.aspx" target="_blank">TaskContinationOptions</a> enumeration, which provides hints to the <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskscheduler.aspx" target="_blank">TaskScheduler</a> that it should only continue based on the operation of the antecedent task.</p>
<p align="left">This is especially useful when dealing with exceptions.&#160; For example, we can extend <a href="http://reedcopsey.com/2010/04/19/parallelism-in-net-part-17-think-continuations-not-callbacks/" target="_blank">the sample from our earlier continuation discussion</a> to include support for handling exceptions thrown by the Factorize method:</p>
<pre class="csharpcode"><span class="rem">// Get a copy of the UI-thread task scheduler up front to use later</span>
var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();

<span class="rem">// Start our task</span>
var factorize = Task.Factory.StartNew(
    () =&gt;
        {
            <span class="kwrd">int</span> primeFactor1 = 0;
            <span class="kwrd">int</span> primeFactor2 = 0;
            <span class="kwrd">bool</span> result = Factorize(10298312, <span class="kwrd">ref</span> primeFactor1, <span class="kwrd">ref</span> primeFactor2);
            <span class="kwrd">return</span> <span class="kwrd">new</span> {
                           Result = result,
                           Factor1 = primeFactor1,
                           Factor2 = primeFactor2
                       };
        });

<span class="rem">// When we succeed, report the results to the UI</span>
factorize.ContinueWith(task =&gt; textBox1.Text = <span class="kwrd">string</span>.Format(<span class="str">&quot;{0}/{1}  [Succeeded {2}]&quot;</span>,
                                 task.Result.Factor1,
                                 task.Result.Factor2,
                                 task.Result.Result),
                        CancellationToken.None,
                        TaskContinuationOptions.NotOnFaulted,
                        uiScheduler);

<span class="rem">// When we have an exception, report it</span>
factorize.ContinueWith(task =&gt; 
                             textBox1.Text = <span class="kwrd">string</span>.Format(<span class="str">&quot;Error: {0}&quot;</span>, task.Exception.Message),
                        CancellationToken.None,
                        TaskContinuationOptions.OnlyOnFaulted,
                        uiScheduler);</pre>
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>The above code works by using a combination of features.&#160; First, we schedule our task, the same way as in <a href="http://reedcopsey.com/2010/04/19/parallelism-in-net-part-17-think-continuations-not-callbacks/" target="_blank">the previous example</a>.&#160; However, in this case, we use a different overload of <a href="http://msdn.microsoft.com/en-us/library/dd991174.aspx" target="_blank">Task.ContinueWith</a> which allows us to specify both a specific TaskScheduler (in order to have your continuation run on the UIâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s synchronization context) as well as a <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskcontinuationoptions.aspx" target="_blank">TaskContinuationOption</a>.&#160; </p>
<p>In the first continuation, we tell the continuation that we only want it to run when there was not an exception by specifying <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskcontinuationoptions.aspx" target="_blank">TaskContinuationOptions.NotOnFaulted</a>.&#160; When our factorize task completes successfully, this continuation will automatically run on the UI thread, and provide the appropriate feedback.</p>
<p>However, if the factorize task has an exception â€“ for example, if the Factorize method throws an exception due to an improper input value, the second continuation will run.&#160; This occurs due to the specification of <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskcontinuationoptions.aspx" target="_blank">TaskContinuationOptions.OnlyOnFaulted</a> in the options.&#160; In this case, weâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />ll report the error received to the user.</p>
<p>We can use <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskcontinuationoptions.aspx" target="_blank">TaskContinuationOptions</a> to filter our continuations by whether or not an exception occurred and whether or not a task was cancelled.&#160; This allows us to handle many situations, and is especially useful when trying to maintain a valid application state without ever blocking the user interface.&#160; The same concepts can be extended even further, and allow you to chain together many tasks based on the success of the previous ones.&#160; Continuations can even be used to <a href="http://blogs.msdn.com/b/pfxteam/archive/2010/02/09/9960735.aspx" target="_blank">create a state machine</a> with full error handling, all without blocking the user interface thread.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2010/10/26/parallelism-in-net-part-19-taskcontinuationoptions/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>Parallelism in .NET &#8211; Part 18, Task Continuations with Multiple Tasks</title>
		<link>http://reedcopsey.com/2010/07/19/parallelism-in-net-part-18-task-continuations-with-multiple-tasks/</link>
					<comments>http://reedcopsey.com/2010/07/19/parallelism-in-net-part-18-task-continuations-with-multiple-tasks/#comments</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Tue, 20 Jul 2010 01:18:37 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Parallelism]]></category>
		<category><![CDATA[.NET 4]]></category>
		<category><![CDATA[C# 4]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/2010/07/19/parallelism-in-net-part-18-task-continuations-with-multiple-tasks/</guid>

					<description><![CDATA[In my introduction to Task continuations I demonstrated how the Task class provides a more expressive alternative to traditional callbacks.&#160; Task continuations provide a much cleaner syntax to traditional callbacks, but there are other reasons to switch to using continuationsâ€¦ Task continuations provide a clean syntax, and a very simple, elegant means of synchronizing asynchronous [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>In my <a href="http://reedcopsey.com/2010/04/19/parallelism-in-net-part-17-think-continuations-not-callbacks/" target="_blank">introduction to Task continuations</a> I demonstrated how the <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx" target="_blank">Task class</a> provides a more expressive alternative to <a href="http://en.wikipedia.org/wiki/Callback_(computer_science)" target="_blank">traditional callbacks</a>.&#160; <a href="http://msdn.microsoft.com/en-us/library/ee372288.aspx" target="_blank">Task continuations</a> provide a much cleaner syntax to traditional callbacks, but there are other reasons to switch to using continuationsâ€¦</p>
<p> <span id="more-282"></span>  </p>
<p><a href="http://msdn.microsoft.com/en-us/library/ee372288.aspx" target="_blank">Task continuations</a> provide a clean syntax, and a very simple, elegant means of synchronizing asynchronous method results with the user interface.&#160; In addition, continuations provide a very simple, elegant means of working with collections of tasks.</p>
<p>Prior to .NET 4, working with multiple related asynchronous method calls was very tricky.&#160; If, for example, we wanted to run two asynchronous operations, followed by a single method call which we wanted to run when the first two methods completed, weâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />d have to program all of the handling ourselves.&#160; We would likely need to take some approach such as using a shared callback which synchronized against a common variable, or using a <a href="http://msdn.microsoft.com/en-us/library/system.threading.waithandle.aspx" target="_blank">WaitHandle</a> shared within the callbacks to allow one to wait for the second.&#160; Although this could be accomplished easily enough, it requires manually placing this handling into every algorithm which requires this form of blocking.&#160; This is error prone, difficult, and can easily lead to subtle bugs.</p>
<p>Similar to how the <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx" target="_blank">Task class</a> static methods providing a way to <a href="http://reedcopsey.com/2010/03/15/parallelism-in-net-part-13-introducing-the-task-class/" target="_blank">block until multiple tasks have completed</a>, <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory.aspx" target="_blank">TaskFactory</a> contains static methods which allow a continuation to be scheduled upon the completion of multiple tasks: <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory.continuewhenall.aspx" target="_blank">TaskFactory.ContinueWhenAll</a>.</p>
<p>This allows you to easily specify a single delegate to run when a collection of tasks has completed.&#160; For example, suppose we have a class which fetches data from the network.&#160; This can be a long running operation, and potentially fail in certain situations, such as a server being down.&#160; As a result, we have three separate servers which we will â€œqueryâ€ for our information.&#160; Now, suppose we want to grab data from all three servers, and verify that the results are the same from all three.</p>
<p>With traditional asynchronous programming in .NET, this would require using three separate callbacks, and managing the synchronization between the various operations ourselves.&#160; The <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx" target="_blank">Task</a> and <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory.aspx" target="_blank">TaskFactory</a> classes simplify this for us, allowing us to write:</p>
<pre class="csharpcode">var server1 = Task.Factory.StartNew( 
                 () =&gt; networkClass.GetResults(firstServer) );
var server2 = Task.Factory.StartNew( 
                 () =&gt; networkClass.GetResults(secondServer) );
var server3 = Task.Factory.StartNew( 
                 () =&gt; networkClass.GetResults(thirdServer) );

var result = Task.Factory.ContinueWhenAll( <span class="kwrd">new</span>[] {server1, server2, server3 },
                 (tasks) =&gt; 
                 {
                       <span class="rem">// Propogate exceptions (see below)</span>
                       Task.WaitAll(tasks);

                       return <span class="kwrd">this</span>.CompareTaskResults(
                               tasks[0].Result,
                               tasks[1].Result,
                               tasks[2].Result);
                  });</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>This is clean, simple, and elegant.&#160; The one complication is the Task.WaitAll(tasks); statement.</p>
<p>Although the continuation will not complete until all three tasks (server1, server2, and server3) have completed, there is a potential snag.&#160; If the networkClass.GetResults method fails, and raises an exception, we want to make sure to handle it cleanly.&#160; By using Task.WaitAll, any exceptions raised within any of our original tasks will get wrapped into a single <a href="http://msdn.microsoft.com/en-us/library/system.aggregateexception.aspx" target="_blank">AggregateException</a> by the <a href="http://msdn.microsoft.com/en-us/library/dd270695.aspx" target="_blank">WaitAll</a> method, providing us a simplified means of handling the exceptions.&#160; If we wait on the continuation, we can trap this <a href="http://msdn.microsoft.com/en-us/library/system.aggregateexception.aspx" target="_blank">AggregateException</a>, and handle it cleanly.&#160; Without this line, itâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s possible that an exception could remain uncaught and <em>unhandled </em>by a task, which later might trigger a nasty <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskscheduler.unobservedtaskexception.aspx" target="_blank">UnobservedTaskException</a>.&#160; This would happen any time two of our original tasks failed.</p>
<p>Just as we can schedule a continuation to occur when an entire collection of tasks has completed, we can just as easily setup a continuation to run when any single task within a collection completes.&#160; If, for example, we didnâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t need to compare the results of all three network locations, but only use one, we could still schedule three tasks.&#160; We could then have our completion logic work on the first task which completed, and ignore the others.&#160; This is done via <a href="http://msdn.microsoft.com/en-us/library/dd321530.aspx" target="_blank">TaskFactory.ContinueWhenAny</a>:</p>
<pre class="csharpcode">var server1 = Task.Factory.StartNew( 
                 () =&gt; networkClass.GetResults(firstServer) );
var server2 = Task.Factory.StartNew( 
                 () =&gt; networkClass.GetResults(secondServer) );
var server3 = Task.Factory.StartNew( 
                 () =&gt; networkClass.GetResults(thirdServer) );

var result = Task.Factory.ContinueWhenAny( <span class="kwrd">new</span>[] {server1, server2, server3 },
                 (firstTask) =&gt; 
                 {
                       <span class="kwrd">return</span> <span class="kwrd">this</span>.ProcessTaskResult(firstTask.Result);
                  });</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>Here, instead of working with all three tasks, weâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />re just using the first task which finishes.&#160; This is very useful, as it allows us to easily work with results of multiple operations, and â€œthrow awayâ€ the others.&#160; However, you must take care when using <a href="http://msdn.microsoft.com/en-us/library/dd321530.aspx" target="_blank">ContinueWhenAny</a> to properly handle exceptions.&#160; At some point, you should always wait on each task (or use the Task.Result property) in order to propogate any exceptions raised from within the task.&#160; Failing to do so can lead to an <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskscheduler.unobservedtaskexception.aspx" target="_blank">UnobservedTaskException</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2010/07/19/parallelism-in-net-part-18-task-continuations-with-multiple-tasks/feed/</wfw:commentRss>
			<slash:comments>19</slash:comments>
		
		
			</item>
		<item>
		<title>Parallelism in .NET &#8211; Part 17, Think Continuations, not Callbacks</title>
		<link>http://reedcopsey.com/2010/04/19/parallelism-in-net-part-17-think-continuations-not-callbacks/</link>
					<comments>http://reedcopsey.com/2010/04/19/parallelism-in-net-part-17-think-continuations-not-callbacks/#comments</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Mon, 19 Apr 2010 20:27:40 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Parallelism]]></category>
		<category><![CDATA[.NET 4]]></category>
		<category><![CDATA[C# 4]]></category>
		<category><![CDATA[Windows Forms]]></category>
		<category><![CDATA[WPF]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/2010/04/19/parallelism-in-net-part-17-think-continuations-not-callbacks/</guid>

					<description><![CDATA[In traditional asynchronous programming, weâ€™d often use a callback to handle notification of a background taskâ€™s completion.&#160; The Task class in the Task Parallel Library introduces a cleaner alternative to the traditional callback: continuation tasks. Asynchronous programming methods typically required callback functions.&#160; For example, MSDNâ€™s Asynchronous Delegates Programming Sample shows a class that factorizes a [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>In traditional asynchronous programming, weâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />d often use a <a href="http://en.wikipedia.org/wiki/Callback_(computer_science)" target="_blank">callback</a> to handle notification of a background taskâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s completion.&#160; The <a href="http://msdn.microsoft.com/en-us/library/dd235678(v=VS.100).aspx" target="_blank">Task class</a> in the <a href="http://msdn.microsoft.com/en-us/library/dd460717(VS.100).aspx" target="_blank">Task Parallel Library</a> introduces a cleaner alternative to the traditional <a href="http://en.wikipedia.org/wiki/Callback_(computer_science)" target="_blank">callback</a>: <a href="http://msdn.microsoft.com/en-us/library/ee372288.aspx" target="_blank">continuation tasks</a>.</p>
<p> <span id="more-272"></span>  </p>
<p>Asynchronous programming methods typically required callback functions.&#160; For example, MSDNâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s <a href="http://msdn.microsoft.com/en-us/library/h80ttd5f(VS.90).aspx" target="_blank">Asynchronous Delegates Programming Sample</a> shows a class that factorizes a number.&#160; The original method in the example has the following signature:</p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">bool</span> Factorize(<span class="kwrd">int</span> number, <span class="kwrd">ref</span> <span class="kwrd">int</span> primefactor1, <span class="kwrd">ref</span> <span class="kwrd">int</span> primefactor2)
{
 //...</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>However, calling this is quite â€œtrickyâ€, even if we modernize the sample to use lambda expressions via C# 3.0.&#160; </p>
<p>Normally, we could call this method like so:</p>
<pre class="csharpcode"><span class="kwrd">int</span> primeFactor1 = 0;
<span class="kwrd">int</span> primeFactor2 = 0;

<span class="kwrd">bool</span> answer = Factorize(10298312, <span class="kwrd">ref</span> primeFactor1, <span class="kwrd">ref</span> primeFactor2);
Console.WriteLine(<span class="str">&quot;{0}/{1}  [Succeeded {2}]&quot;</span>, primeFactor1, primeFactor2, answer);</pre>
<p>If we want to make this operation run in the background, and report to the console via a callback, things get tricker.&#160; First, we need a delegate definition: </p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">delegate</span> <span class="kwrd">bool</span> AsyncFactorCaller(
     <span class="kwrd">int</span> number,
     <span class="kwrd">ref</span> <span class="kwrd">int</span> primefactor1,
     <span class="kwrd">ref</span> <span class="kwrd">int</span> primefactor2);</pre>
<p>Then we need to use BeginInvoke to run this method asynchronously:</p>
<pre class="csharpcode"><span class="kwrd">int</span> primeFactor1 = 0;
<span class="kwrd">int</span> primeFactor2 = 0;

AsyncFactorCaller caller  = <span class="kwrd">new</span> AsyncFactorCaller(Factorize);
caller.BeginInvoke(10298312, <span class="kwrd">ref</span> primeFactor1, <span class="kwrd">ref</span> primeFactor2,
   result =&gt;
       {
           <span class="kwrd">int</span> factor1 = 0;
           <span class="kwrd">int</span> factor2 = 0;
           <span class="kwrd">bool</span> answer = caller.EndInvoke(<span class="kwrd">ref</span> factor1, <span class="kwrd">ref</span> factor2, result);
           Console.WriteLine(<span class="str">&quot;{0}/{1}  [Succeeded {2}]&quot;</span>, factor1, factor2, answer);
       }, <span class="kwrd">null</span>);</pre>
<p>This works, but is quite difficult to understand from a conceptual standpoint.&#160; To combat this, the framework added the <a href="http://msdn.microsoft.com/en-us/library/wewwczdw(VS.90).aspx" target="_blank">Event-based Asynchronous Pattern</a>, but it isnâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t much easier to understand or author. </p>
<p>Using .NET 4â€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s new Task&lt;T&gt; class and a continuation, we can dramatically simplify the implementation of the above code, as well as make it much more understandable.&#160; We do this via the <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.continuewith.aspx" target="_blank">Task.ContinueWith</a> method.&#160; This method will schedule a new Task upon completion of the original task, and provide the original Task (including its Result if itâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s a <a href="http://msdn.microsoft.com/en-us/library/dd321424.aspx" target="_blank">Task&lt;T&gt;</a>) as an argument.&#160; Using Task, we can eliminate the delegate, and rewrite this code like so:</p>
<pre class="csharpcode">var background = Task.Factory.StartNew(
    () =&gt;
        {
            <span class="kwrd">int</span> primeFactor1 = 0;
            <span class="kwrd">int</span> primeFactor2 = 0;
            <span class="kwrd">bool</span> result = Factorize(10298312, <span class="kwrd">ref</span> primeFactor1, <span class="kwrd">ref</span> primeFactor2);
            <span class="kwrd">return</span> <span class="kwrd">new </span>{
                           Result = result,
                           Factor1 = primeFactor1,
                           Factor2 = primeFactor2
                       };
        });
background.ContinueWith(task =&gt; Console.WriteLine(<span class="str">&quot;{0}/{1}  [Succeeded {2}]&quot;</span>,
                                 task.Result.Factor1,
                                 task.Result.Factor2,
                                 task.Result.Result));</pre>
<p>This is much simpler to understand, in my opinion.&#160; Here, weâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />re explicitly asking to start a new task, then <strong>continue</strong> the task with a resulting task.&#160; In our case, our method used ref parameters (this was from the MSDN Sample), so there is a little bit of extra boiler plate involved, but the code is at least easy to understand.</p>
<p>That being said, this isnâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />t dramatically shorter when compared with our C# 3 port of the MSDN code above.&#160; However, if we were to extend our requirements a bit, we can start to see more advantages to the Task based approach.&#160; For example, supposed we need to report the results in a user interface control instead of reporting it to the Console.&#160; This would be a common operation, but now, we have to think about marshaling our calls back to the user interface.&#160; This is probably going to require calling Control.Invoke or Dispatcher.Invoke within our callback, forcing us to specify a delegate within the delegate.&#160; The maintainability and ease of understanding drops.&#160; However, just as a standard <a href="http://reedcopsey.com/2010/03/18/parallelism-in-net-part-15-making-tasks-run-the-taskscheduler/" target="_blank">Task can be created with a TaskScheduler that uses the UI synchronization context</a>, so too can we continue a task with a specific context.&#160; There are <a href="http://msdn.microsoft.com/en-us/library/dd321307.aspx" target="_blank">Task.ContinueWith method overloads</a> which allow you to provide a <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskscheduler.aspx" target="_blank">TaskScheduler</a>.&#160; This means you can schedule the continuation to run on the UI thread, by simply doing:</p>
<pre class="csharpcode">Task.Factory.StartNew(
    () =&gt;
        {
            <span class="kwrd">int</span> primeFactor1 = 0;
            <span class="kwrd">int</span> primeFactor2 = 0;
            <span class="kwrd">bool</span> result = Factorize(10298312, <span class="kwrd">ref</span> primeFactor1, <span class="kwrd">ref</span> primeFactor2);
            <span class="kwrd">return</span> <span class="kwrd">new</span> {
                           Result = result,
                           Factor1 = primeFactor1,
                           Factor2 = primeFactor2
                       };
        }).ContinueWith(task =&gt; textBox1.Text = <span class="kwrd">string</span>.Format(<span class="str">&quot;{0}/{1}  [Succeeded {2}]&quot;</span>,
                                 task.Result.Factor1,
                                 task.Result.Factor2,
                                 task.Result.Result), 
                        TaskScheduler.FromCurrentSynchronizationContext());</pre>
<p>This is far more understandable than the alternative.&#160; By using <a href="http://msdn.microsoft.com/en-us/library/dd321307.aspx" target="_blank">Task.ContinueWith</a> in conjunction with <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskscheduler.fromcurrentsynchronizationcontext.aspx" target="_blank">TaskScheduler.FromCurrentSynchronizationContext()</a>, we get a simple way to push any work onto a background thread, and update the user interface on the proper UI thread.&#160; This technique works with Windows Presentation Foundation as well as Windows Forms, with no change in methodology.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2010/04/19/parallelism-in-net-part-17-think-continuations-not-callbacks/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title>Attached Property port of my Window Close Behavior</title>
		<link>http://reedcopsey.com/2010/04/15/attached-property-port-of-my-window-close-behavior/</link>
					<comments>http://reedcopsey.com/2010/04/15/attached-property-port-of-my-window-close-behavior/#respond</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Thu, 15 Apr 2010 21:12:39 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[MVVM]]></category>
		<category><![CDATA[WPF]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/2010/04/15/attached-property-port-of-my-window-close-behavior/</guid>

					<description><![CDATA[Nishant Sivakumar just posted a nice article on The Code Project.&#160; It is a port of the MVVM-friendly Blend Behavior I wrote about in a previous article to WPF using Attached Properties. While similar to the WindowCloseBehavior code I posted on the Expression Code Gallery, Nishant Sivakumarâ€™s version works in WPF without taking a dependency [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><a href="http://blog.voidnish.com/" target="_blank">Nishant Sivakumar</a> just posted a nice article on <a href="http://www.codeproject.com/" target="_blank">The Code Project</a>.&#160; It is a port of the MVVM-friendly Blend Behavior I wrote about in <a href="http://reedcopsey.com/2009/10/09/using-behaviors-to-allow-the-viewmodel-to-manage-view-lifetime-in-m-v-vm/" target="_blank">a previous article</a> to WPF using <a href="http://msdn.microsoft.com/en-us/library/ms749011.aspx" target="_blank">Attached Properties</a>.</p>
<p>While similar to the <a href="http://gallery.expression.microsoft.com/en-us/WindowCloseBehavior" target="_blank">WindowCloseBehavior code I posted on the Expression Code Gallery</a>, <a href="http://www.codeproject.com/KB/WPF/WindowClosingBehavior.aspx" target="_blank">Nishant Sivakumarâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s version</a> works in WPF without taking a dependency on the Expression Blend SDK.</p>
<p>I highly recommend reading this article: <a href="http://www.codeproject.com/KB/WPF/WindowClosingBehavior.aspx" target="_blank">Handling a Windowâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s Closed and Closing Events in the View-Model</a>.&#160; It is a very nice alternative approach to this common problem in MVVM.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2010/04/15/attached-property-port-of-my-window-close-behavior/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>2010 Visual C# MVP Award</title>
		<link>http://reedcopsey.com/2010/04/01/2010-visual-c-mvp-award/</link>
					<comments>http://reedcopsey.com/2010/04/01/2010-visual-c-mvp-award/#comments</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Thu, 01 Apr 2010 23:05:11 +0000</pubDate>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Professional]]></category>
		<category><![CDATA[MVP]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/2010/04/01/2010-visual-c-mvp-award/</guid>

					<description><![CDATA[I received a pleasant surprise today.&#160; I was presented this morning with the 2010 MicrosoftÂ® MVP Award for Visual C#.&#160; According to the award email, this â€œaward is given to exceptional technical community leaders who actively share their high quality, real world expertise with others.â€ I feel honored and proud to receive this award, and [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>I received a pleasant surprise today.&#160; I was presented this morning with the <a href="https://mvp.support.microsoft.com/default.aspx/gp/mvpawardintro" target="_blank">2010 MicrosoftÂ® MVP Award</a> for Visual C#.&#160; According to the award email, this â€œaward is given to exceptional technical community leaders who actively share their high quality, real world expertise with others.â€</p>
<p>I feel honored and proud to receive this award, and hope that I can continue to be a valuable member of the community in the future.&#160; Thank you to everyone who nominated me!</p>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2010/04/01/2010-visual-c-mvp-award/feed/</wfw:commentRss>
			<slash:comments>15</slash:comments>
		
		
			</item>
		<item>
		<title>Parallelism in .NET &#8211; Part 16, Creating Tasks via a TaskFactory</title>
		<link>http://reedcopsey.com/2010/03/26/parallelism-in-net-part-16-creating-tasks-via-a-taskfactory/</link>
					<comments>http://reedcopsey.com/2010/03/26/parallelism-in-net-part-16-creating-tasks-via-a-taskfactory/#comments</comments>
		
		<dc:creator><![CDATA[Reed]]></dc:creator>
		<pubDate>Sat, 27 Mar 2010 00:51:58 +0000</pubDate>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Parallelism]]></category>
		<category><![CDATA[.NET 4]]></category>
		<category><![CDATA[C# 4]]></category>
		<guid isPermaLink="false">http://reedcopsey.com/2010/03/26/parallelism-in-net-part-16-creating-tasks-via-a-taskfactory/</guid>

					<description><![CDATA[The Task class in the Task Parallel Library supplies a large set of features.&#160; However, when creating the task, and assigning it to a TaskScheduler, and starting the Task, there are quite a few steps involved.&#160; This gets even more cumbersome when multiple tasks are involved.&#160; Each task must be constructed, duplicating any options required, [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>The <a href="http://msdn.microsoft.com/en-us/library/dd235678(v=VS.100).aspx" target="_blank">Task class</a> in the <a href="http://msdn.microsoft.com/en-us/library/dd460717(VS.100).aspx" target="_blank">Task Parallel Library</a> supplies a large set of features.&#160; However, when <a href="http://reedcopsey.com/2010/03/17/parallelism-in-net-part-14-the-different-forms-of-task/" target="_blank">creating the task</a>, and <a href="http://reedcopsey.com/2010/03/18/parallelism-in-net-part-15-making-tasks-run-the-taskscheduler/" target="_blank">assigning it to a TaskScheduler</a>, and starting the <a href="http://msdn.microsoft.com/en-us/library/dd235678(v=VS.100).aspx" target="_blank">Task</a>, there are quite a few steps involved.&#160; This gets even more cumbersome when multiple tasks are involved.&#160; Each task must be constructed, duplicating any options required, then started individually, potentially on a specific scheduler.&#160; At first glance, this makes the new <a href="http://msdn.microsoft.com/en-us/library/dd235678(v=VS.100).aspx" target="_blank">Task class</a> seem like more work than <a href="http://msdn.microsoft.com/en-us/library/system.threading.threadpool.queueuserworkitem.aspx" target="_blank">ThreadPool.QueueUserWorkItem</a> in .NET 3.5.</p>
<p>In order to simplify this process, and make Tasks simple to use in simple cases, without sacrificing their power and flexibility, the <a href="http://msdn.microsoft.com/en-us/library/dd460717(VS.100).aspx" target="_blank">Task Parallel Library</a> added a new class: <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory(VS.100).aspx" target="_blank">TaskFactory</a>.</p>
<p> <span id="more-263"></span>  </p>
<p>The <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory(VS.100).aspx" target="_blank">TaskFactory class</a> is intended to â€œProvide support for creating and scheduling Task objects.â€&#160; Its entire purpose is to simplify development when working with <a href="http://msdn.microsoft.com/en-us/library/dd235678(v=VS.100).aspx" target="_blank">Task</a> instances.&#160; The <a href="http://msdn.microsoft.com/en-us/library/dd235678(v=VS.100).aspx" target="_blank">Task</a> class provides access to the default <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory(VS.100).aspx" target="_blank">TaskFactory</a> via the <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.factory(VS.100).aspx" target="_blank">Task.Factory</a> static property.&#160; By default, <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory(VS.100).aspx" target="_blank">TaskFactory</a> uses the <a href="http://reedcopsey.com/2010/03/18/parallelism-in-net-part-15-making-tasks-run-the-taskscheduler/" target="_blank">default TaskScheduler</a> to schedule tasks on a ThreadPool thread.&#160; By using Task.Factory, we can automatically create and start a task in a single â€œfire and forgetâ€ manner, similar to how we did with <a href="http://msdn.microsoft.com/en-us/library/system.threading.threadpool.queueuserworkitem.aspx" target="_blank">ThreadPool.QueueUserWorkItem</a>:</p>
<pre class="csharpcode">Task.Factory.StartNew(() =&gt; <span class="kwrd">this</span>.ExecuteBackgroundWork(myData) );</pre>
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>This provides us with the same level of simplicity we had with <a href="http://msdn.microsoft.com/en-us/library/system.threading.threadpool.queueuserworkitem.aspx" target="_blank">ThreadPool.QueueUserWorkItem</a>, but even more power.&#160; For example, we can now easily wait on the task:</p>
<pre class="csharpcode"><span class="rem">// Start our task on a background thread</span>
var task = Task.Factory.StartNew(() =&gt; <span class="kwrd">this</span>.ExecuteBackgroundWork(myData) );

<span class="rem">// Do other work on the main thread, </span>
<span class="rem">// while the task above executes in the background</span>
<span class="kwrd">this</span>.ExecuteWorkSynchronously();

<span class="rem">// Wait for the background task to finish</span>
task.Wait();</pre>
<p><a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory(VS.100).aspx" target="_blank">TaskFactory</a> simplifies creation and startup of simple background tasks dramatically.</p>
<p>In addition to using the default <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory(VS.100).aspx" target="_blank">TaskFactory</a>, itâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />s often useful to construct a custom <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory(VS.100).aspx" target="_blank">TaskFactory</a>.&#160; The <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory(VS.100).aspx" target="_blank">TaskFactory class</a> includes an entire <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory.taskfactory(VS.100).aspx" target="_blank">set of constructors</a> which allow you to specify the default configuration for every <a href="http://msdn.microsoft.com/en-us/library/dd235678(v=VS.100).aspx" target="_blank">Task</a> instance created by that factory.&#160; </p>
<p>This is particularly useful when <a href="http://reedcopsey.com/2010/03/18/parallelism-in-net-part-15-making-tasks-run-the-taskscheduler/" target="_blank">using a custom TaskScheduler</a>.&#160; For example, look at the <a href="http://reedcopsey.com/2010/03/18/parallelism-in-net-part-15-making-tasks-run-the-taskscheduler/" target="_blank">sample code for starting a task on the UI thread in Part 15</a>:</p>
<pre class="csharpcode"><span class="rem">// Given the following, constructed on the UI thread</span>
<span class="rem">// TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();</span>

<span class="rem">// When inside a background task, we can do</span>
<span class="kwrd">string</span> status = GetUpdatedStatus();

(<span class="kwrd">new</span> Task(() =&gt;
    {
        statusLabel.Text = status;
    }))
.Start(uiScheduler);</pre>
<p>This is actually quite a bit more complicated than necessary.&#160; When we create the <em>uiScheduler</em> instance, we can use that to construct a <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory(VS.100).aspx" target="_blank">TaskFactory</a> that will automatically schedule tasks on the UI thread.&#160; To do that, weâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />d create the following on our main thread, prior to constructing our background tasks:</p>
<pre class="csharpcode"><span class="rem">// Construct a task scheduler from the current SynchronizationContext (UI thread)</span>
var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
<span class="rem">// Construct a new TaskFactory using our UI scheduler</span>
var uiTaskFactory = <span class="kwrd">new</span> TaskFactory(uiScheduler);</pre>
<p>If we do this, when weâ€<img src="https://s.w.org/images/core/emoji/15.0.3/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" />re on a background thread, we can use this new <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory(VS.100).aspx" target="_blank">TaskFactory</a> to marshal a Task back onto the UI thread.&#160; Our previous code simplifies to:</p>
<pre class="csharpcode"><span class="rem">// When inside a background task, we can do</span>
<span class="kwrd">string</span> status = GetUpdatedStatus();

<span class="rem">// Update our UI</span>
uiTaskFactory.StartNew( () =&gt; statusLabel.Text = status);</pre>
<p>Notice how much simpler this becomes!&#160; By taking advantage of the convenience provided by a custom <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskfactory(VS.100).aspx" target="_blank">TaskFactory</a>, we can now marshal to set data on the UI thread in a single, clear line of code!</p>
]]></content:encoded>
					
					<wfw:commentRss>http://reedcopsey.com/2010/03/26/parallelism-in-net-part-16-creating-tasks-via-a-taskfactory/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
	</channel>
</rss>
 