diffable Wiki Rss Feedhttp://diffable.codeplex.com/diffable Wiki Rss DescriptionUpdated Wiki: Unit Testing Examplehttp://diffable.codeplex.com/wikipage?title=Unit Testing Example&version=3<div class="wikidoc">Though diffable is applicable to general F# debugging, DiffBundle's structuralEquiv field can be used as a tool for unit testing. Below is an example of a test written for the <a href="http://www.nunit.org" class="externalLink">NUnit<span class="externalLinkIcon"></span></a> unit testing framework, and which uses <a href="http://fsunit.codeplex.com" class="externalLink">FsUnit<span class="externalLinkIcon"></span></a> as well.<br /><br /><pre>
[<TestFixture>]
type DiffableExample () =
[<Test>]
member test.orderIndependent () =
let values0 = [1;3;2;5]
let values1 = [2;5;1;3]
let tree0 = List.fold insert EmptyBST values0
let tree1 = List.fold insert EmptyBST values1
let compare t0 t1 =
if diffHelpers.structuralEquiv t0 t1 then
true
else
let seq0 = List.scan insert EmptyBST values0
viewDOTGraph (treeListDOTCode seq0)
let seq1 = List.scan insert EmptyBST values1
viewDOTGraph (treeListDOTCode seq1)
false
(compare tree0 tree1) |> should be (equal true)
</pre> </div><div class="ClearBoth"></div>kevinclancyThu, 02 Jun 2011 19:35:11 GMTUpdated Wiki: Unit Testing Example 20110602073511PUpdated Wiki: Tutorialhttp://diffable.codeplex.com/wikipage?title=Tutorial&version=12<div class="wikidoc">Let's say we're programming a binary search tree data structure. We represent binary search trees using values of the following discriminated union type:<br /><pre>
type BST =
| Internal of BST*BST*int
| ValLeaf of int
| NilLeaf
</pre><br />Our union has three cases. Internal is used to represent nodes that have children. Its fields, in order, are its left child, its right child, and the value it contains. ValLeaf is used to represent nodes that do not have children, i.e. leaves. Finally, NilLeaf is a placeholder; if an internal node only has one child, NilLeaf is used as the value for its other child.<br /><br />We construct binary search trees using the following insert function:<br /><pre>
let rec insert (bst : BST) (n : int) =
match bst with
| Internal(leftChild,rightChild,value) ->
if n <= value then
Internal(insert leftChild n, rightChild, value)
else
Internal(leftChild, insert rightChild n, value)
| ValLeaf(value) ->
if n <= value then
Internal(ValLeaf(n), NilLeaf, value)
else
Internal(NilLeaf, ValLeaf(n), value)
| NilLeaf ->
ValLeaf(n)
</pre><br />Let's say we want to generate an image of one of our binary search trees that displays the structure of our tree, as well as the values it contains and the depth of each node. To do this we must first define a diffInfo function, which provides some extra information about our BST type.<br /><br /><pre>
let diffInfo (bst : BST) (depth : int) =
match bst with
| Internal(leftChild, rightChild, value) ->
{
nodeLabel = value.ToString() + " (" + depth.ToString() + ")"
children = [(leftChild, depth+1, "<="); (rightChild, depth+1, ">")]
compFields = [value]
}
| ValLeaf(value) ->
{
nodeLabel = value.ToString() + " (" + depth.ToString() + ")"
children = []
compFields = [value]
}
| NilLeaf ->
{
nodeLabel = "*"
children = []
compFields = []
}
</pre><br />A diffInfo function has two parameters. The first is a value belonging to the inductively-defined datatype that we wish to view an image of. <br /><br />The second is a context value. Context, which is passed to a node from its parent, is used to store information that can't be synthesized from the subtree that node is the root of. Context contains information regarding parents, ancestors, siblings, etc.<br /><br />In our case, we're using the depth of a node as its context. A node's depth certainly can not be deduced by examining the subtree it is the root of, so depth is an appropriate choice for a context field.<br /><br />A diffInfo function returns a value belonging to the DiffInfo<'Diffable, 'Context> record type, which contains the following fields:<br />nodeLabel:<br />The label that we want to give the current node in our diagram.<br /><br />children:<br />A list of triples of the form (child, context, edgeLabel), where child is a 'Diffable value representing a node that current node has an outgoing edge to, context is the context we wish to pass to child, and edgeLabel is the label that we want to give the outgoing edge from the current node to child.<br /><br />compFields:<br />Used to define equality between two 'Diffable values. Diffable considers two values equal if they belong to the same union case, have children lists of equal length, have compFields lists of equal length, and their corresponding elements of compFields are equal with respect to the = operator. <br /><br />To use the above diffInfo function to generate graphs for BST values, we call the Diffable.diffBundle function.<br /><br /><pre>
let diffHelpers = Diffable.diffBundle diffInfo 0
</pre><br />The first argument to diffBundle is the diffInfo function we have defined, while the second argument is the value we wish to use as an empty context (i.e. the context to use for a node with no parents).<br /><br />Now we are ready to generate some DOT graphs.<br /><br /><pre>
let EmptyBST = NilLeaf
let values = [3;4;-4;2]
let tree = List.fold insert EmptyBST values
let treeDOTGraph (diffHelpers.treeDOTCode tree)
let treeList = List.scan insert EmptyBST values
let listDOTGraph (diffHelpers.treeListDOTCode treeList)
</pre><br />The above code will bind treeDOTGraph to DOT code for the tree resulting from inserting the values 3,4,-4, and 2 into an empty tree. listDOTGraph, on the other hand, will be bound to DOT code for a sequence of trees containing every intermediate tree during the insertion of the values.<br /><br />It is the user's responsibility to convert the DOT code that Diffable generates into images. I recommend compiling the DOT code to SVG files using <a href="http://www.graphviz.org" class="externalLink">Graphviz<span class="externalLinkIcon"></span></a>, and then viewing the SVG files using <a href="http://xmlgraphics.apache.org/batik/tools/browser.html" class="externalLink">Squiggle<span class="externalLinkIcon"></span></a>.<br /><br />If both of the above tools are in your path, you can use the following function to automatically carry out the above process.<br /><br /><pre>
let viewDOTGraph (string : string) =
let outStream = new StreamWriter("temp.dot")
outStream.Write string
outStream.Close()
//Create a new process to build an svg based on the graphviz
//file we have just written.
let graphvizProc = System.Diagnostics.Process.Start(
"dot",
"-Tsvg -o \"temp.svg\" -Kdot \"temp.dot\""
)
graphvizProc.WaitForExit()
//Display the svg in a viewer.
let squiggleProc = System.Diagnostics.Process.Start(
"batik-squiggle.jar",
"temp.svg"
)
()
</pre><br />Here is the image that graphviz would generate from treeDOTGraph:<br /><img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=diffable&DownloadId=242259" alt="DiffableDocFig1.png" title="DiffableDocFig1.png" /><br /><br />Here is the image that graphviz would generate from listDOTGraph:<br /><img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=diffable&DownloadId=242261" alt="DiffableDocFig2.png" title="DiffableDocFig2.png" /><br /><br />Notice that certain nodes have been highlighted red in the above graph. These are nodes that either were not present in the previous tree in the list, or are somehow different from the corresponding node in the previous tree.<br /><br /></div><div class="ClearBoth"></div>kevinclancyThu, 02 Jun 2011 18:47:13 GMTUpdated Wiki: Tutorial 20110602064713PUpdated Wiki: Homehttp://diffable.codeplex.com/wikipage?version=31<div class="wikidoc"><h1>Project Description</h1>
Diffable is an F# library that makes it easy and natural to write unit tests involving values belonging to discriminated union types. It provides functions that generate DOT code representing such values as directed graphs, so that any test failures can be quickly debugged. <br /><br /><br />
<h1>Motivation</h1>
Discriminated union types play a central role in F# programming; however, they don't play nicely with unit tests. Suppose we are writing a unit test involving a value belonging to a discriminated union type. We likely obtain this value as the result of some functional transformation, and we would like our test to assert that this value satisfies a certain property.<br /><br />If our test were to fail, and we couldn't figure out why simply by reading through its code, the next logical course of action would be to employ the debugger. We would place a breakpoint in our test and inspect the items involved. In a typical object-oriented unit test, we would be inspecting objects containing localized numeric, boolean, and string data. The debugger works quite well for these tasks. In our case, we instead have to deal with a complex linked structure. Navigating this structure using the debugger is clunky to say the least. A better way to navigate this structure is by viewing a graph image of it. Diffable makes the generation of such images easy and natural.<br /><br />A common type of unit test involving discriminated unions involves asserting the structural equivalence of two union values. In such cases, Diffable generates an image displaying graphs of both values side-by-side; differing subgraphs are highlighted red. This shows the difference, or "diff", of the two values and is the source of the name Diffable.<br /><br /></div><div class="ClearBoth"></div>kevinclancyThu, 02 Jun 2011 18:46:10 GMTUpdated Wiki: Home 20110602064610PUpdated Wiki: Homehttp://diffable.codeplex.com/wikipage?version=30<div class="wikidoc"><h1>Project Description</h1>
Diffable is an F# library that makes it easy and natural to write unit tests involving values belonging to discriminated union types. It provides functions that generate DOT code representing such values as directed graphs, so that any test failures can be quickly debugged. <br /><br /><br />
<h1>Motivation</h1>
Discriminated union types play a central role in F# programming; however, they don't play nicely with unit tests. Suppose we are writing a unit test involving a value belonging to a discriminated union type. We likely obtain this value as the result of some functional transformation, and we would like our test to assert that this value satisfies a certain property.<br /><br />If our test were to fail, and we couldn't figure out why simply be reading through its code, the next logical course of action would be to employ the debugger. We would place a breakpoint in our test and inspect the items involved. In a typical object-oriented unit test, we would be inspecting objects containing localized numeric, boolean, and string data. The debugger works quite well for these tasks. In our case, we instead have to deal with a complex linked structure. Navigating this structure using the debugger is clunky to say the least. A better way to navigate this structure is by viewing a graph image of it. Diffable makes the generation of such images easy and natural.<br /><br />A common type of unit test involving discriminated unions involves asserting the structural equivalence of two union values. In such cases, Diffable generates an image displaying graphs of both values side-by-side; differing subgraphs are highlighted red. This shows the difference, or "diff", of the two values and is the source of the name Diffable.<br /><br /></div><div class="ClearBoth"></div>kevinclancyMon, 23 May 2011 20:52:32 GMTUpdated Wiki: Home 20110523085232PUpdated Wiki: Tutorialhttp://diffable.codeplex.com/wikipage?title=Tutorial&version=11<div class="wikidoc">Let's say we're programming a binary search tree data structure. We represent binary search trees using values of the following discriminated union type:<br /><pre>
type BST =
| Internal of BST*BST*int
| ValLeaf of int
| NilLeaf
</pre><br />Our union has three cases. Internal is used to represent nodes that have children. Its fields, in order, are its left child, its right child, and the value it contains. ValLeaf is used to represent nodes that do not have children, i.e. leaves. Finally, NilLeaf is a placeholder; if an internal node only has one child, NilLeaf is used as the value for its other child.<br /><br />We construct binary search trees using the following insert function:<br /><pre>
let rec insert (bst : BST) (n : int) =
match bst with
| Internal(leftChild,rightChild,value) ->
if n <= value then
Internal(insert leftChild n, rightChild, value)
else
Internal(leftChild, insert rightChild n, value)
| ValLeaf(value) ->
if n <= value then
Internal(ValLeaf(n), NilLeaf, value)
else
Internal(NilLeaf, ValLeaf(n), value)
| NilLeaf ->
ValLeaf(n)
</pre><br />Let's say we want to generate an image of one of our of our binary search trees that displays the structure of our tree, as well as the values it contains and the depth of each node. To do this we must first define a diffInfo function, which provides some extra information about our BST type.<br /><br /><pre>
let diffInfo (bst : BST) (depth : int) =
match bst with
| Internal(leftChild, rightChild, value) ->
{
nodeLabel = value.ToString() + " (" + depth.ToString() + ")"
children = [(leftChild, depth+1, "<="); (rightChild, depth+1, ">")]
compFields = [value]
}
| ValLeaf(value) ->
{
nodeLabel = value.ToString() + " (" + depth.ToString() + ")"
children = []
compFields = [value]
}
| NilLeaf ->
{
nodeLabel = "*"
children = []
compFields = []
}
</pre><br />A diffInfo function has two parameters. The first is a value belonging to the inductively-defined datatype that we wish to view an image of. <br /><br />The second is a context value. Context, which is passed to a node from its parent, is used to store information that can't be synthesized from the subtree that node is the root of. Context contains information regarding parents, ancestors, siblings, etc.<br /><br />In our case, we're using the depth of a node as its context. A node's depth certainly can not be deduced by examining the subtree it is the root of, so depth is an appropriate choice for a context field.<br /><br />A diffInfo function returns a value belonging to the DiffInfo<'Diffable, 'Context> record type, which contains the following fields:<br />nodeLabel:<br />The label that we want to give the current node in our diagram.<br /><br />children:<br />A list of triples of the form (child, context, edgeLabel), where child is a 'Diffable value representing a node that current node has an outgoing edge to, context is the context we wish to pass to child, and edgeLabel is the label that we want to give the outgoing edge from the current node to child.<br /><br />compFields:<br />Used to define equality between two 'Diffable values. Diffable considers two values equal if they belong to the same union case, have children lists of equal length, have compFields lists of equal length, and their corresponding elements of compFields are equal with respect to the = operator. <br /><br />To use the above diffInfo function to generate graphs for BST values, we call the Diffable.diffBundle function.<br /><br /><pre>
let diffHelpers = Diffable.diffBundle diffInfo 0
</pre><br />The first argument to diffBundle is the diffInfo function we have defined, while the second argument is the value we wish to use as an empty context (i.e. the context to use for a node with no parents).<br /><br />Now we are ready to generate some DOT graphs.<br /><br /><pre>
let EmptyBST = NilLeaf
let values = [3;4;-4;2]
let tree = List.fold insert EmptyBST values
let treeDOTGraph (diffHelpers.treeDOTCode tree)
let treeList = List.scan insert EmptyBST values
let listDOTGraph (diffHelpers.treeListDOTCode treeList)
</pre><br />The above code will bind treeDOTGraph to DOT code for the tree resulting from inserting the values 3,4,-4, and 2 into an empty tree. listDOTGraph, on the other hand, will be bound to DOT code for a sequence of trees containing every intermediate tree during the insertion of the values.<br /><br />It is the user's responsibility to convert the DOT code that Diffable generates into images. I recommend compiling the DOT code to SVG files using <a href="http://www.graphviz.org" class="externalLink">Graphviz<span class="externalLinkIcon"></span></a>, and then viewing the SVG files using <a href="http://xmlgraphics.apache.org/batik/tools/browser.html" class="externalLink">Squiggle<span class="externalLinkIcon"></span></a>.<br /><br />If both of the above tools are in your path, you can use the following function to automatically carry out the above process.<br /><br /><pre>
let viewDOTGraph (string : string) =
let outStream = new StreamWriter("temp.dot")
outStream.Write string
outStream.Close()
//Create a new process to build an svg based on the graphviz
//file we have just written.
let graphvizProc = System.Diagnostics.Process.Start(
"dot",
"-Tsvg -o \"temp.svg\" -Kdot \"temp.dot\""
)
graphvizProc.WaitForExit()
//Display the svg in a viewer.
let squiggleProc = System.Diagnostics.Process.Start(
"batik-squiggle.jar",
"temp.svg"
)
()
</pre><br />Here is the image that graphviz would generate from treeDOTGraph:<br /><img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=diffable&DownloadId=242259" alt="DiffableDocFig1.png" title="DiffableDocFig1.png" /><br /><br />Here is the image that graphviz would generate from listDOTGraph:<br /><img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=diffable&DownloadId=242261" alt="DiffableDocFig2.png" title="DiffableDocFig2.png" /><br /><br />Notice that certain nodes have been highlighted red in the above graph. These are nodes that either were not present in the previous tree in the list, or are somehow different from the corresponding node in the previous tree.<br /><br /></div><div class="ClearBoth"></div>kevinclancySun, 22 May 2011 20:15:14 GMTUpdated Wiki: Tutorial 20110522081514PUpdated Wiki: Tutorialhttp://diffable.codeplex.com/wikipage?title=Tutorial&version=10<div class="wikidoc">Let's say we're programming a binary search tree data structure. We represent binary search trees using values of the following discriminated union type:<br /><pre>
type BST =
| Internal of BST*BST*int
| ValLeaf of int
| NilLeaf
</pre><br />Our union has three cases. Internal is used to represent nodes that have children. Its fields, in order, are its left child, its right child, and the value it contains. ValLeaf is used to represent nodes that do not have children, i.e. leaves. Finally, NilLeaf is a placeholder; if an internal node only has one child, NilLeaf is used as the value for its other child.<br /><br />We construct binary search trees using the following insert function:<br /><pre>
let rec insert (bst : BST) (n : int) =
match bst with
| Internal(leftChild,rightChild,value) ->
if n <= value then
Internal(insert leftChild n, rightChild, value)
else
Internal(leftChild, insert rightChild n, value)
| ValLeaf(value) ->
if n <= value then
Internal(ValLeaf(n), NilLeaf, value)
else
Internal(NilLeaf, ValLeaf(n), value)
| NilLeaf ->
ValLeaf(n)
</pre><br />Let's say we want to generate an image of one of our of our binary search trees that displays the structure of our tree, as well as the values it contains and the depth of each node. To do this we must first define a diffInfo function, which provides some extra information about our BST type.<br /><br /><pre>
let diffInfo (bst : BST) (depth : int) =
match bst with
| Internal(leftChild, rightChild, value) ->
{
nodeLabel = value.ToString() + " (" + depth.ToString() + ")"
children = [(leftChild, depth+1, "<="); (rightChild, depth+1, ">")]
compFields = [value]
}
| ValLeaf(value) ->
{
nodeLabel = value.ToString() + " (" + depth.ToString() + ")"
children = []
compFields = [value]
}
| NilLeaf ->
{
nodeLabel = "*"
children = []
compFields = []
}
</pre><br />A diffInfo function has two parameters. The first is a value belonging to the inductively-defined datatype that we wish to view an image of. <br /><br />The second is a context value. Context, which is passed to a node from its parent, is used to store information that can't be synthesized from the subtree that node is the root of. Context contains information regarding parents, ancestors, siblings, etc.<br /><br />In our case, we're using the depth of a node as its context. A node's depth certainly could not be deduced by examining the subtree it is the root of, so depth is an appropriate choice for a context field.<br /><br />A diffInfo function returns a value belonging to the DiffInfo<'Diffable, 'Context> record type, which contains the following fields:<br />nodeLabel:<br />The label that we want to give the current node in our diagram.<br /><br />children:<br />A list of triples of the form (child, context, edgeLabel), where child is a 'Diffable value representing a node that current node has an outgoing edge to, context is the context we wish to pass to child, and edgeLabel is the label that we want to give the outgoing edge from the current node to child.<br /><br />compFields:<br />Used to define equality between two 'Diffable values. Diffable considers two values equal if they belong to the same union case, have children lists of equal length, have compFields lists of equal length, and their corresponding elements of compFields are equal with respect to the = operator. <br /><br />To use the above diffInfo function to generate graphs for BST values, we call the Diffable.diffBundle function.<br /><br /><pre>
let diffHelpers = Diffable.diffBundle diffInfo 0
</pre><br />The first argument to diffBundle is the diffInfo function we have defined, while the second argument is the value we wish to use as an empty context (i.e. the context to use for a node with no parents).<br /><br />Now we are ready to generate some DOT graphs.<br /><br /><pre>
let EmptyBST = NilLeaf
let values = [3;4;-4;2]
let tree = List.fold insert EmptyBST values
let treeDOTGraph (diffHelpers.treeDOTCode tree)
let treeList = List.scan insert EmptyBST values
let listDOTGraph (diffHelpers.treeListDOTCode treeList)
</pre><br />The above code will bind treeDOTGraph to DOT code for the tree resulting from inserting the values 3,4,-4, and 2 into an empty tree. listDOTGraph, on the other hand, will be bound to DOT code for a sequence of trees containing every intermediate tree during the insertion of the values.<br /><br />It is the user's responsibility to convert the DOT code that Diffable generates into images. I recommend compiling the DOT code to SVG files using <a href="http://www.graphviz.org" class="externalLink">Graphviz<span class="externalLinkIcon"></span></a>, and then viewing the SVG files using <a href="http://xmlgraphics.apache.org/batik/tools/browser.html" class="externalLink">Squiggle<span class="externalLinkIcon"></span></a>.<br /><br />If both of the above tools are in your path, you can use the following function to automatically carry out the above process.<br /><br /><pre>
let viewDOTGraph (string : string) =
let outStream = new StreamWriter("temp.dot")
outStream.Write string
outStream.Close()
//Create a new process to build an svg based on the graphviz
//file we have just written.
let graphvizProc = System.Diagnostics.Process.Start(
"dot",
"-Tsvg -o \"temp.svg\" -Kdot \"temp.dot\""
)
graphvizProc.WaitForExit()
//Display the svg in a viewer.
let squiggleProc = System.Diagnostics.Process.Start(
"batik-squiggle.jar",
"temp.svg"
)
()
</pre><br />Here is the image that graphviz would generate from treeDOTGraph:<br /><img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=diffable&DownloadId=242259" alt="DiffableDocFig1.png" title="DiffableDocFig1.png" /><br /><br />Here is the image that graphviz would generate from listDOTGraph:<br /><img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=diffable&DownloadId=242261" alt="DiffableDocFig2.png" title="DiffableDocFig2.png" /><br /><br />Notice that certain nodes have been highlighted red in the above graph. These are nodes that either were not present in the previous tree in the list, or are somehow different from the corresponding node in the previous tree.<br /><br /></div><div class="ClearBoth"></div>kevinclancySun, 22 May 2011 20:14:49 GMTUpdated Wiki: Tutorial 20110522081449PUpdated Wiki: Documentationhttp://diffable.codeplex.com/documentation?version=9<div class="wikidoc"><a href="http://diffable.codeplex.com/wikipage?title=Installation&referringTitle=Documentation">Installation</a><br /><a href="http://diffable.codeplex.com/wikipage?title=Tutorial&referringTitle=Documentation">Tutorial</a><br /><a href="http://diffable.codeplex.com/wikipage?title=Unit%20Testing%20Example&referringTitle=Documentation">Unit Testing Example</a><br /><br /></div><div class="ClearBoth"></div>kevinclancySun, 22 May 2011 19:51:05 GMTUpdated Wiki: Documentation 20110522075105PUpdated Wiki: Documentationhttp://diffable.codeplex.com/documentation?version=8<div class="wikidoc"><a href="http://diffable.codeplex.com/wikipage?title=Installation&referringTitle=Documentation">Installation</a><br /><a href="http://diffable.codeplex.com/wikipage?title=Tutorial%201%20-%20Introduction&referringTitle=Documentation">Tutorial 1 - Introduction</a><br /><a href="http://diffable.codeplex.com/wikipage?title=Tutorial&referringTitle=Documentation">Tutorial</a><br /><a href="http://diffable.codeplex.com/wikipage?title=Unit%20Testing%20Example&referringTitle=Documentation">Unit Testing Example</a><br /><br /></div><div class="ClearBoth"></div>kevinclancySun, 22 May 2011 19:49:39 GMTUpdated Wiki: Documentation 20110522074939PUpdated Wiki: Documentationhttp://diffable.codeplex.com/documentation?version=7<div class="wikidoc"><a href="http://diffable.codeplex.com/wikipage?title=Installation&referringTitle=Documentation">Installation</a><br /><a href="http://diffable.codeplex.com/wikipage?title=Tutorial%201%20-%20Introduction&referringTitle=Documentation">Tutorial 1 - Introduction</a><br /><a href="http://diffable.codeplex.com/wikipage?title=Introduction&referringTitle=Documentation">Introduction</a><br /><a href="http://diffable.codeplex.com/wikipage?title=Unit%20Testing%20Example&referringTitle=Documentation">Unit Testing Example</a><br /><br /></div><div class="ClearBoth"></div>kevinclancySun, 22 May 2011 19:49:11 GMTUpdated Wiki: Documentation 20110522074911PUpdated Wiki: Unit Testing Examplehttp://diffable.codeplex.com/wikipage?title=Unit Testing Example&version=2<div class="wikidoc">Though diffable is applicable to general F# debugging, DiffBundle's structuralEquiv field can be used as a tool for unit testing. Below is an example of a test written for the <a href="http://www.nunit.org" class="externalLink">NUnit<span class="externalLinkIcon"></span></a><br />unit testing framework, and which uses <a href="http://fsunit.codeplex.com" class="externalLink">FsUnit<span class="externalLinkIcon"></span></a> as well.<br /><br /><pre>
[<TestFixture>]
type DiffableExample () =
[<Test>]
member test.orderIndependent () =
let values0 = [1;3;2;5]
let values1 = [2;5;1;3]
let tree0 = List.fold insert EmptyBST values0
let tree1 = List.fold insert EmptyBST values1
let compare t0 t1 =
if diffHelpers.structuralEquiv t0 t1 then
true
else
let seq0 = List.scan insert EmptyBST values0
viewDOTGraph (treeListDOTCode seq0)
let seq1 = List.scan insert EmptyBST values1
viewDOTGraph (treeListDOTCode seq1)
false
(compare tree0 tree1) |> should be (equal true)
</pre> </div><div class="ClearBoth"></div>kevinclancySun, 22 May 2011 19:46:59 GMTUpdated Wiki: Unit Testing Example 20110522074659PUpdated Wiki: Unit Testing Examplehttp://diffable.codeplex.com/wikipage?title=Unit Testing Example&version=1<div class="wikidoc">Though diffable is applicable to general F# debugging, DiffBundle's structuralEquiv field can be used as a tool for unit testing. Below is an example of a test written for the NUnit unit testing framework, and which uses FsUnit as well.<br /><br /><pre>
[<TestFixture>]
type DiffableExample () =
[<Test>]
member test.orderIndependent () =
let values0 = [1;3;2;5]
let values1 = [2;5;1;3]
let tree0 = List.fold insert EmptyBST values0
let tree1 = List.fold insert EmptyBST values1
let compare t0 t1 =
if diffHelpers.structuralEquiv t0 t1 then
true
else
let seq0 = List.scan insert EmptyBST values0
viewDOTGraph (treeListDOTCode seq0)
let seq1 = List.scan insert EmptyBST values1
viewDOTGraph (treeListDOTCode seq1)
false
(compare tree0 tree1) |> should be (equal true)
</pre> </div><div class="ClearBoth"></div>kevinclancySun, 22 May 2011 19:40:48 GMTUpdated Wiki: Unit Testing Example 20110522074048PUpdated Wiki: Documentationhttp://diffable.codeplex.com/documentation?version=6<div class="wikidoc"><a href="http://diffable.codeplex.com/wikipage?title=Installation&referringTitle=Documentation">Installation</a><br /><a href="http://diffable.codeplex.com/wikipage?title=Tutorial%201%20-%20Introduction&referringTitle=Documentation">Tutorial 1 - Introduction</a><br /><a href="http://diffable.codeplex.com/wikipage?title=Unit%20Testing%20Example&referringTitle=Documentation">Unit Testing Example</a><br /><br /></div><div class="ClearBoth"></div>kevinclancySun, 22 May 2011 19:40:39 GMTUpdated Wiki: Documentation 20110522074039PUpdated Wiki: Tutorial 2 - Unit Testinghttp://diffable.codeplex.com/wikipage?title=Tutorial 2 - Unit Testing&version=1<div class="wikidoc">Though diffable is applicable to general F# debugging, DiffBundle's structuralEquiv field can be used as a tool for unit testing. Below is an example of a test written for the NUnit unit testing framework, and which uses FsUnit as well.<br /><br /><pre>
[<TestFixture>]
type DiffableExample () =
[<Test>]
member test.orderIndependent () =
let values0 = [1;3;2;5]
let values1 = [2;5;1;3]
let tree0 = List.fold insert EmptyBST values0
let tree1 = List.fold insert EmptyBST values1
let compare t0 t1 =
if diffHelpers.structuralEquiv t0 t1 then
true
else
let seq0 = List.scan insert EmptyBST values0
viewDOTGraph (treeListDOTCode seq0)
let seq1 = List.scan insert EmptyBST values1
viewDOTGraph (treeListDOTCode seq1)
false
(compare tree0 tree1) |> should be (equal true)
</pre> </div><div class="ClearBoth"></div>kevinclancySun, 22 May 2011 19:39:31 GMTUpdated Wiki: Tutorial 2 - Unit Testing 20110522073931PUpdated Wiki: Tutorial 1 - Introductionhttp://diffable.codeplex.com/wikipage?title=Tutorial 1 - Introduction&version=4<div class="wikidoc">Let's say we're programming a binary search tree data structure. We represent binary search trees using values of the following discriminated union type:<br /><pre>
type BST =
| Internal of BST*BST*int
| ValLeaf of int
| NilLeaf
</pre><br />Our union has three cases. Internal is used to represent nodes that have children. Its fields, in order, are its left child, its right child, and the value it contains. ValLeaf is used to represent nodes that do not have children, i.e. leaves. Finally, NilLeaf is a placeholder; if an internal node only has one child, NilLeaf is used as the value for its other child.<br /><br />We construct binary search trees using the following insert function:<br /><pre>
let rec insert (bst : BST) (n : int) =
match bst with
| Internal(leftChild,rightChild,value) ->
if n <= value then
Internal(insert leftChild n, rightChild, value)
else
Internal(leftChild, insert rightChild n, value)
| ValLeaf(value) ->
if n <= value then
Internal(ValLeaf(n), NilLeaf, value)
else
Internal(NilLeaf, ValLeaf(n), value)
| NilLeaf ->
ValLeaf(n)
</pre><br />Let's say we want to generate an image of one of our of our binary search trees that displays the structure of our tree, as well as the values it contains and the depth of each node. To do this we must first define a diffInfo function which provides some extra information about our BST type.<br /><br /><pre>
let diffInfo (bst : BST) (depth : int) =
match bst with
| Internal(leftChild, rightChild, value) ->
{
nodeLabel = value.ToString() + " (" + depth.ToString() + ")"
children = [(leftChild, depth+1, "<="); (rightChild, depth+1, ">")]
compFields = [value]
}
| ValLeaf(value) ->
{
nodeLabel = value.ToString() + " (" + depth.ToString() + ")"
children = []
compFields = [value]
}
| NilLeaf ->
{
nodeLabel = "*"
children = []
compFields = []
}
</pre><br />A diffInfo function has two parameters. The first is a value belonging to the inductively-defined datatype that we wish to view an image of. <br /><br />The second is a context value. Context, which is passed to a node from its parent, is used to store information that can't be synthesized from the subtree that node is the root of. Context contains information regarding parents, ancestors, siblings, etc.<br /><br />In our case, we're using the depth of a node as its context. A node's depth certainly could not be deduced by examining the subtree it is the root of, so depth is an appropriate choice for a context field.<br /><br />A diffInfo function returns a value belonging to the DiffInfo<'Diffable, 'Context> record type, which contains the following fields:<br />nodeLabel:<br />The label that we want to give the current node in our diagram.<br /><br />children:<br />A list of triples of the form (child, context, edgeLabel), where child is a 'Diffable value representing a node that current node has an outgoing edge to, context is the context we wish to pass to child, and edgeLabel is the label that we want to give the outgoing edge from the current node to child.<br /><br />compFields:<br />Used to define equality between two 'Diffable values. Diffable considers two values equal if they belong to the same union case, have children lists of equal length, have compFields lists of equal length, and their corresponding elements of compFields are equal with respect to the = operator. <br /><br />To use the above diffInfo function to generate graphs for BST values, we call the Diffable.diffBundle function.<br /><br /><pre>
let diffHelpers = Diffable.diffBundle diffInfo 0
</pre><br />The first argument to diffBundle is the diffInfo function we have defined, while the second argument is the value we wish to use as an empty context (i.e. the context to use for a node with no parents).<br /><br />Now we are ready to generate some DOT graphs.<br /><br /><pre>
let EmptyBST = NilLeaf
let values = [3;4;-4;2]
let tree = List.fold insert EmptyBST values
let treeDOTGraph (diffHelpers.treeDOTCode tree)
let treeList = List.scan insert EmptyBST values
let listDOTGraph (diffHelpers.treeListDOTCode treeList)
</pre><br />The above code will bind treeDOTGraph to DOT code for the tree resulting from inserting the values 3,4,-4, and 2 into an empty tree. listDOTGraph, on the other hand, will be bound to DOT code for a sequence of trees containing every intermediate tree during the insertion of the values.<br /><br />It is the user's responsibility to convert the DOT code that Diffable generates into images. I recommend compiling the DOT code to SVG files using <a href="http://www.graphviz.org" class="externalLink">Graphviz<span class="externalLinkIcon"></span></a>, and then viewing the SVG files using <a href="http://xmlgraphics.apache.org/batik/tools/browser.html" class="externalLink">Squiggle<span class="externalLinkIcon"></span></a>.<br /><br />If both of the above tools are in your path, you can use the following function to automatically carry out the above process.<br /><br /><pre>
let viewDOTGraph (string : string) =
let outStream = new StreamWriter("temp.dot")
outStream.Write string
outStream.Close()
//Create a new process to build an svg based on the graphviz
//file we have just written.
let graphvizProc = System.Diagnostics.Process.Start(
"dot",
"-Tsvg -o \"temp.svg\" -Kdot \"temp.dot\""
)
graphvizProc.WaitForExit()
//Display the svg in a viewer.
let squiggleProc = System.Diagnostics.Process.Start(
"batik-squiggle.jar",
"temp.svg"
)
()
</pre><br />Here is the image that graphviz would generate from treeDOTGraph:<br /><img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=diffable&DownloadId=242277" alt="DiffableDocFig1.png" title="DiffableDocFig1.png" /><br /><br />Here is the image that graphviz would generate from listDOTGraph:<br /><img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=diffable&DownloadId=242276" alt="DiffableDocFig2.png" title="DiffableDocFig2.png" /><br /><br />Notice that certain nodes have been highlighted red in the above graph. These are nodes that either were not present in the previous tree in the list, or are somehow different from the corresponding node in the previous tree.<br /><br /></div><div class="ClearBoth"></div>kevinclancySun, 22 May 2011 19:01:43 GMTUpdated Wiki: Tutorial 1 - Introduction 20110522070143PUpdated Wiki: Tutorial 1 - Introductionhttp://diffable.codeplex.com/wikipage?title=Tutorial 1 - Introduction&version=3<div class="wikidoc">Let's say we're programming a binary search tree data structure. We represent binary search trees using values of the following discriminated union type:<br /><pre>
type BST =
| Internal of BST*BST*int
| ValLeaf of int
| NilLeaf
</pre><br />Our union has three cases. Internal is used to represent nodes that have children. Its fields, in order, are its left child, its right child, and the value it contains. ValLeaf is used to represent nodes that do not have children, i.e. leaves. Finally, NilLeaf is a placeholder; if an internal node only has one child, NilLeaf is used as the value for its other child.<br /><br />We construct binary search trees using the following insert function:<br /><pre>
let rec insert (bst : BST) (n : int) =
match bst with
| Internal(leftChild,rightChild,value) ->
if n <= value then
Internal(insert leftChild n, rightChild, value)
else
Internal(leftChild, insert rightChild n, value)
| ValLeaf(value) ->
if n <= value then
Internal(ValLeaf(n), NilLeaf, value)
else
Internal(NilLeaf, ValLeaf(n), value)
| NilLeaf ->
ValLeaf(n)
</pre><br />Let's say we want to generate an image of one of our of our binary search trees that displays the structure of our tree, as well as the values it contains and the depth of each node. To do this we must first define a diffInfo function which provides some extra information about our BST type.<br /><br /><pre>
let diffInfo (bst : BST) (depth : int) =
match bst with
| Internal(leftChild, rightChild, value) ->
{
nodeLabel = value.ToString() + " (" + depth.ToString() + ")"
children = [(leftChild, depth+1, "<="); (rightChild, depth+1, ">")]
compFields = [value]
}
| ValLeaf(value) ->
{
nodeLabel = value.ToString() + " (" + depth.ToString() + ")"
children = []
compFields = [value]
}
| NilLeaf ->
{
nodeLabel = "*"
children = []
compFields = []
}
</pre><br />A diffInfo function has two parameters. The first is a value belonging to the inductively-defined datatype that we wish to view an image of. <br /><br />The second is a context value. Context, which is passed to a node from its parent, is used to store information that can't be synthesized from the subtree that node is the root of. Context contains information regarding parents, ancestors, siblings, etc.<br /><br />In our case, we're using the depth of a node as its context. A node's depth certainly could not be deduced by examining the subtree it is the root of, so depth is an appropriate choice for a context field.<br /><br />A diffInfo function returns a value belonging to the DiffInfo<'Diffable, 'Context> record type, which contains the following fields:<br />nodeLabel:<br />The label that we want to give the current node in our diagram.<br /><br />children:<br />A list of triples of the form (child, context, edgeLabel), where child is a 'Diffable value representing a node that current node has an outgoing edge to, context is the context we wish to pass to child, and edgeLabel is the label that we want to give the outgoing edge from the current node to child.<br /><br />compFields:<br />Used to define equality between two 'Diffable values. Diffable considers two values equal if they belong to the same union case, have children lists of equal length, have compFields lists of equal length, and their corresponding elements of compFields are equal with respect to the = operator. <br /><br />To use the above diffInfo function to generate graphs for BST values, we call the Diffable.diffBundle function.<br /><br /><pre>
let diffHelpers = Diffable.diffBundle diffInfo 0
</pre><br />The first argument to diffBundle is the diffInfo function we have defined, while the second argument is the value we wish to use as an empty context (i.e. the context to use for a node with no parents).<br /><br />Now we are ready to generate some DOT graphs.<br /><br /><pre>
let EmptyBST = NilLeaf
let values = [3;4;-4;2]
let tree = List.fold insert EmptyBST values
let treeDOTGraph (diffHelpers.treeDOTCode tree)
let treeList = List.scan insert EmptyBST values
let listDOTGraph (diffHelpers.treeListDOTCode treeList)
</pre><br />The above code will bind treeDOTGraph to DOT code for the tree resulting from inserting the values 3,4,-4, and 2 into an empty tree. listDOTGraph, on the other hand, will be bound to DOT code for a sequence of trees containing every intermediate tree during the insertion of the values.<br /><br />It is the user's responsibility to convert the DOT code that Diffable generates into images. I recommend compiling the DOT code to SVG files using <a href="http://www.graphviz.org" class="externalLink">Graphviz<span class="externalLinkIcon"></span></a>, and then viewing the SVG files using <a href="http://xmlgraphics.apache.org/batik/tools/browser.html" class="externalLink">Squiggle<span class="externalLinkIcon"></span></a>.<br /><br />If both of the above tools are in your path, you can use the following function to automatically carry out the above process.<br /><br /><pre>
let viewDOTGraph (string : string) =
let outStream = new StreamWriter("temp.dot")
outStream.Write string
outStream.Close()
//Create a new process to build an svg based on the graphviz
//file we have just written.
let graphvizProc = System.Diagnostics.Process.Start(
"dot",
"-Tsvg -o \"temp.svg\" -Kdot \"temp.dot\""
)
graphvizProc.WaitForExit()
//Display the svg in a viewer.
let squiggleProc = System.Diagnostics.Process.Start(
"batik-squiggle.jar",
"temp.svg"
)
()
</pre><br />Here is the image that graphviz would generate from treeDOTGraph:<br /><span class="unresolved">Cannot resolve image macro, invalid image name or id.</span><br /><br />Here is the image that graphviz would generate from listDOTGraph:<br /><img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=diffable&DownloadId=242276" alt="DiffableDocFig2.png" title="DiffableDocFig2.png" /><br /><br />Notice that certain nodes have been highlighted red in the above graph. These are nodes that either were not present in the previous tree in the list, or are somehow different from the corresponding node in the previous tree.<br /><br /></div><div class="ClearBoth"></div>kevinclancySun, 22 May 2011 19:01:23 GMTUpdated Wiki: Tutorial 1 - Introduction 20110522070123PUpdated Wiki: Tutorial 1 - Introductionhttp://diffable.codeplex.com/wikipage?title=Tutorial 1 - Introduction&version=2<div class="wikidoc">Let's say we're programming a binary search tree data structure. We represent binary search trees using values of the following discriminated union type:<br /><pre>
type BST =
| Internal of BST*BST*int
| ValLeaf of int
| NilLeaf
</pre><br />Our union has three cases. Internal is used to represent nodes that have children. Its fields, in order, are its left child, its right child, and the value it contains. ValLeaf is used to represent nodes that do not have children, i.e. leaves. Finally, NilLeaf is a placeholder; if an internal node only has one child, NilLeaf is used as the value for its other child.<br /><br />We construct binary search trees using the following insert function:<br /><pre>
let rec insert (bst : BST) (n : int) =
match bst with
| Internal(leftChild,rightChild,value) ->
if n <= value then
Internal(insert leftChild n, rightChild, value)
else
Internal(leftChild, insert rightChild n, value)
| ValLeaf(value) ->
if n <= value then
Internal(ValLeaf(n), NilLeaf, value)
else
Internal(NilLeaf, ValLeaf(n), value)
| NilLeaf ->
ValLeaf(n)
</pre><br />Let's say we want to generate an image of one of our of our binary search trees that displays the structure of our tree, as well as the values it contains and the depth of each node. To do this we must first define a diffInfo function which provides some extra information about our BST type.<br /><br /><pre>
let diffInfo (bst : BST) (depth : int) =
match bst with
| Internal(leftChild, rightChild, value) ->
{
nodeLabel = value.ToString() + " (" + depth.ToString() + ")"
children = [(leftChild, depth+1, "<="); (rightChild, depth+1, ">")]
compFields = [value]
}
| ValLeaf(value) ->
{
nodeLabel = value.ToString() + " (" + depth.ToString() + ")"
children = []
compFields = [value]
}
| NilLeaf ->
{
nodeLabel = "*"
children = []
compFields = []
}
</pre><br />A diffInfo function has two parameters. The first is a value belonging to the inductively-defined datatype that we wish to view an image of. <br /><br />The second is a context value. Context, which is passed to a node from its parent, is used to store information that can't be synthesized from the subtree that node is the root of. Context contains information regarding parents, ancestors, siblings, etc.<br /><br />In our case, we're using the depth of a node as its context. A node's depth certainly could not be deduced by examining the subtree it is the root of, so depth is an appropriate choice for a context field.<br /><br />A diffInfo function returns a value belonging to the DiffInfo<'Diffable, 'Context> record type, which contains the following fields:<br />nodeLabel:<br />The label that we want to give the current node in our diagram.<br /><br />children:<br />A list of triples of the form (child, context, edgeLabel), where child is a 'Diffable value representing a node that current node has an outgoing edge to, context is the context we wish to pass to child, and edgeLabel is the label that we want to give the outgoing edge from the current node to child.<br /><br />compFields:<br />Used to define equality between two 'Diffable values. Diffable considers two values equal if they belong to the same union case, have children lists of equal length, have compFields lists of equal length, and their corresponding elements of compFields are equal with respect to the = operator. <br /><br />To use the above diffInfo function to generate graphs for BST values, we call the Diffable.diffBundle function.<br /><br /><pre>
let diffHelpers = Diffable.diffBundle diffInfo 0
</pre><br />The first argument to diffBundle is the diffInfo function we have defined, while the second argument is the value we wish to use as an empty context (i.e. the context to use for a node with no parents).<br /><br />Now we are ready to generate some DOT graphs.<br /><br /><pre>
let EmptyBST = NilLeaf
let values = [3;4;-4;2]
let tree = List.fold insert EmptyBST values
let treeDOTGraph (diffHelpers.treeDOTCode tree)
let treeList = List.scan insert EmptyBST values
let listDOTGraph (diffHelpers.treeListDOTCode treeList)
</pre><br />The above code will bind treeDOTGraph to DOT code for the tree resulting from inserting the values 3,4,-4, and 2 into an empty tree. listDOTGraph, on the other hand, will be bound to DOT code for a sequence of trees containing every intermediate tree during the insertion of the values.<br /><br />It is the user's responsibility to convert the DOT code that Diffable generates into images. I recommend compiling the DOT code to SVG files using <a href="http://www.graphviz.org" class="externalLink">Graphviz<span class="externalLinkIcon"></span></a>, and then viewing the SVG files using <a href="http://xmlgraphics.apache.org/batik/tools/browser.html" class="externalLink">Squiggle<span class="externalLinkIcon"></span></a>.<br /><br />If both of the above tools are in your path, you can use the following function to automatically carry out the above process.<br /><br /><pre>
let viewDOTGraph (string : string) =
let outStream = new StreamWriter("temp.dot")
outStream.Write string
outStream.Close()
//Create a new process to build an svg based on the graphviz
//file we have just written.
let graphvizProc = System.Diagnostics.Process.Start(
"dot",
"-Tsvg -o \"temp.svg\" -Kdot \"temp.dot\""
)
graphvizProc.WaitForExit()
//Display the svg in a viewer.
let squiggleProc = System.Diagnostics.Process.Start(
"batik-squiggle.jar",
"temp.svg"
)
()
</pre><br />Here is the image that graphviz would generate from treeDOTGraph:<br /><img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=diffable&DownloadId=242275" alt="DiffableDocFig1.png" title="DiffableDocFig1.png" /><br /><br />Here is the image that graphviz would generate from listDOTGraph:<br /><img src="http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=diffable&DownloadId=242276" alt="DiffableDocFig2.png" title="DiffableDocFig2.png" /><br /><br />Notice that certain nodes have been highlighted red in the above graph. These are nodes that either were not present in the previous tree in the list, or are somehow different from the corresponding node in the previous tree.<br /><br /></div><div class="ClearBoth"></div>kevinclancySun, 22 May 2011 19:00:23 GMTUpdated Wiki: Tutorial 1 - Introduction 20110522070023PUpdated Wiki: Tutorial 1 - Introductionhttp://diffable.codeplex.com/wikipage?title=Tutorial 1 - Introduction&version=1<div class="wikidoc">Let's say we're programming a binary search tree data structure. We represent binary search trees using values of the following discriminated union type:<br /><pre>
type BST =
| Internal of BST*BST*int
| ValLeaf of int
| NilLeaf
</pre><br />Our union has three cases. Internal is used to represent nodes that have children. Its fields, in order, are its left child, its right child, and the value it contains. ValLeaf is used to represent nodes that do not have children, i.e. leaves. Finally, NilLeaf is a placeholder; if an internal node only has one child, NilLeaf is used as the value for its other child.<br /><br />We construct binary search trees using the following insert function:<br /><pre>
let rec insert (bst : BST) (n : int) =
match bst with
| Internal(leftChild,rightChild,value) ->
if n <= value then
Internal(insert leftChild n, rightChild, value)
else
Internal(leftChild, insert rightChild n, value)
| ValLeaf(value) ->
if n <= value then
Internal(ValLeaf(n), NilLeaf, value)
else
Internal(NilLeaf, ValLeaf(n), value)
| NilLeaf ->
ValLeaf(n)
</pre><br />Let's say we want to generate an image of one of our of our binary search trees that displays the structure of our tree, as well as the values it contains and the depth of each node. To do this we must first define a diffInfo function which provides some extra information about our BST type.<br /><br /><pre>
let diffInfo (bst : BST) (depth : int) =
match bst with
| Internal(leftChild, rightChild, value) ->
{
nodeLabel = value.ToString() + " (" + depth.ToString() + ")"
children = [(leftChild, depth+1, "<="); (rightChild, depth+1, ">")]
compFields = [value]
}
| ValLeaf(value) ->
{
nodeLabel = value.ToString() + " (" + depth.ToString() + ")"
children = []
compFields = [value]
}
| NilLeaf ->
{
nodeLabel = "*"
children = []
compFields = []
}
</pre><br />A diffInfo function has two parameters. The first is a value belonging to the inductively-defined datatype that we wish to view an image of. <br /><br />The second is a context value. Context, which is passed to a node from its parent, is used to store information that can't be synthesized from the subtree that node is the root of. Context contains information regarding parents, ancestors, siblings, etc.<br /><br />In our case, we're using the depth of a node as its context. A node's depth certainly could not be deduced by examining the subtree it is the root of, so depth is an appropriate choice for a context field.<br /><br />A diffInfo function returns a value belonging to the DiffInfo<'Diffable, 'Context> record type, which contains the following fields:<br />nodeLabel:<br />The label that we want to give the current node in our diagram.<br /><br />children:<br />A list of triples of the form (child, context, edgeLabel), where child is a 'Diffable value representing a node that current node has an outgoing edge to, context is the context we wish to pass to child, and edgeLabel is the label that we want to give the outgoing edge from the current node to child.<br /><br />compFields:<br />Used to define equality between two 'Diffable values. Diffable considers two values equal if they belong to the same union case, have children lists of equal length, have compFields lists of equal length, and their corresponding elements of compFields are equal with respect to the = operator. <br /><br />To use the above diffInfo function to generate graphs for BST values, we call the Diffable.diffBundle function.<br /><br /><pre>
let diffHelpers = Diffable.diffBundle diffInfo 0
</pre><br />The first argument to diffBundle is the diffInfo function we have defined, while the second argument is the value we wish to use as an empty context (i.e. the context to use for a node with no parents).<br /><br />Now we are ready to generate some DOT graphs.<br /><br /><pre>
let EmptyBST = NilLeaf
let values = [3;4;-4;2]
let tree = List.fold insert EmptyBST values
let treeDOTGraph (diffHelpers.treeDOTCode tree)
let treeList = List.scan insert EmptyBST values
let listDOTGraph (diffHelpers.treeListDOTCode treeList)
</pre><br />The above code will bind treeDOTGraph to DOT code for the tree resulting from inserting the values 3,4,-4, and 2 into an empty tree. listDOTGraph, on the other hand, will be bound to DOT code for a sequence of trees containing every intermediate tree during the insertion of the values.<br /><br />It is the user's responsibility to convert the DOT code that Diffable generates into images. I recommend compiling the DOT code to SVG files using <a href="http://www.graphviz.org" class="externalLink">Graphviz<span class="externalLinkIcon"></span></a>, and then viewing the SVG files using <a href="http://xmlgraphics.apache.org/batik/tools/browser.html" class="externalLink">Squiggle<span class="externalLinkIcon"></span></a>.<br /><br />If both of the above tools are in your path, you can use the following function to automatically carry out the above process.<br /><br /><pre>
let viewDOTGraph (string : string) =
let outStream = new StreamWriter("temp.dot")
outStream.Write string
outStream.Close()
//Create a new process to build an svg based on the graphviz
//file we have just written.
let graphvizProc = System.Diagnostics.Process.Start(
"dot",
"-Tsvg -o \"temp.svg\" -Kdot \"temp.dot\""
)
graphvizProc.WaitForExit()
//Display the svg in a viewer.
let squiggleProc = System.Diagnostics.Process.Start(
"batik-squiggle.jar",
"temp.svg"
)
()
</pre><br />Here is the image that graphviz would generate from treeDOTGraph:<br /><span class="unresolved">Cannot resolve image macro, invalid image name or id.</span><br /><br />Here is the image that graphviz would generate from listDOTGraph:<br /><span class="unresolved">Cannot resolve image macro, invalid image name or id.</span><br /><br />Notice that certain nodes have been highlighted red in the above graph. These are nodes that either were not present in the previous tree in the list, or are somehow different from the corresponding node in the previous tree.<br /><br /></div><div class="ClearBoth"></div>kevinclancySun, 22 May 2011 18:59:39 GMTUpdated Wiki: Tutorial 1 - Introduction 20110522065939PUpdated Wiki: Documentationhttp://diffable.codeplex.com/documentation?version=5<div class="wikidoc"><a href="http://diffable.codeplex.com/wikipage?title=Installation&referringTitle=Documentation">Installation</a><br /><a href="http://diffable.codeplex.com/wikipage?title=Tutorial%201%20-%20Introduction&referringTitle=Documentation">Tutorial 1 - Introduction</a><br /><a href="http://diffable.codeplex.com/wikipage?title=Tutorial%202%20-%20Unit%20Testing&referringTitle=Documentation">Tutorial 2 - Unit Testing</a><br /><br /></div><div class="ClearBoth"></div>kevinclancySun, 22 May 2011 18:59:16 GMTUpdated Wiki: Documentation 20110522065916PUpdated Wiki: Documentationhttp://diffable.codeplex.com/documentation?version=4<div class="wikidoc"><a href="http://diffable.codeplex.com/wikipage?title=Installation&referringTitle=Documentation">Installation</a><br /><a href="http://diffable.codeplex.com/wikipage?title=Tutorial%201%20-Introduction&referringTitle=Documentation">Tutorial 1 -Introduction</a><br /><a href="http://diffable.codeplex.com/wikipage?title=Tutorial%202%20-%20Unit%20Testing&referringTitle=Documentation">Tutorial 2 - Unit Testing</a><br /><br /></div><div class="ClearBoth"></div>kevinclancySun, 22 May 2011 18:59:02 GMTUpdated Wiki: Documentation 20110522065902PUpdated Wiki: Documentationhttp://diffable.codeplex.com/documentation?version=3<div class="wikidoc"><a href="http://diffable.codeplex.com/wikipage?title=Installation&referringTitle=Documentation">Installation</a><br /><a href="http://diffable.codeplex.com/wikipage?title=Introduction&referringTitle=Documentation">Introduction</a><br /><a href="http://diffable.codeplex.com/wikipage?title=Tutorial%202%20-%20Unit%20Testing&referringTitle=Documentation">Tutorial 2 - Unit Testing</a><br /><br /></div><div class="ClearBoth"></div>kevinclancySun, 22 May 2011 18:58:06 GMTUpdated Wiki: Documentation 20110522065806P