Permalink
Browse files

C# compat for RoseTree

  • Loading branch information...
mausch committed Oct 16, 2012
1 parent a37a573 commit 46b510e4d83e71af5e8a0113e5ff6f6f2d207914
@@ -6,6 +6,7 @@ open System.Net
open System.Collections.Generic
open System.Runtime.CompilerServices
open Microsoft.FSharp.Control.WebExtensions
+open FSharpx.DataStructures
/// Helps the C# compiler with Func type inference.
type L =
@@ -482,4 +483,22 @@ type FSharpAsyncEx =
type FSharpLazy =
static member Create (v: _ Func) = Lazy.Create v.Invoke
- static member CreateFromValue v = Lazy.CreateFromValue v
+ static member CreateFromValue v = Lazy.CreateFromValue v
+
+[<Extension>]
+type RoseTree =
+ static member Singleton x = RoseTree.singleton x
+ static member Create(root, [<ParamArray>] children) = RoseTree.create root (LazyList.ofArray children)
+ static member Create(root, children) = RoseTree.create root children
+
+ [<Extension>]
+ static member Select(tree, f: Func<_,_>) = RoseTree.map f.Invoke tree
+
+ [<Extension>]
+ static member SelectMany (o, f: Func<_,_>) = RoseTree.bind f.Invoke o
+
+ [<Extension>]
+ static member SelectMany (o, f: Func<_,_>, mapper: Func<_,_,_>) =
+ let mapper = RoseTree.lift2 (curry mapper.Invoke)
+ let v = RoseTree.bind f.Invoke o
+ mapper o v
@@ -2,6 +2,7 @@
open System
open System.Linq
+open System.Runtime.CompilerServices
/// Multi-way tree, also known as rose tree.
// Ported from http://hackage.haskell.org/packages/archive/containers/latest/doc/html/src/Data-Tree.html
@@ -26,6 +27,7 @@ and 'a RoseForest = 'a RoseTree LazyList
module L = LazyList
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
+[<Extension>]
module RoseTree =
let inline create root children = { Root = root; Children = children }
@@ -49,12 +51,16 @@ module RoseTree =
{ RoseTree.Root = a.Root
Children = L.append a.Children (L.map (bind f) x.Children) }
+ [<CompiledName("DfsPre")>]
+ [<Extension>]
let rec dfsPre (x: _ RoseTree) =
seq {
yield x.Root
yield! Seq.collect dfsPre x.Children
}
+ [<CompiledName("DfsPost")>]
+ [<Extension>]
let rec dfsPost (x: _ RoseTree) =
seq {
yield! Seq.collect dfsPost x.Children
@@ -47,6 +47,7 @@
<Reference Include="FSharp.Core" Condition="$(TargetFrameworkVersion) == 'v3.5'">
<HintPath>..\..\lib\FSharp\Net20\FSharp.Core.dll</HintPath>
</Reference>
+ <Reference Include="FSharp.PowerPack, Version=2.0.0.0, Culture=neutral, PublicKeyToken=a19089b1c74d0809, processorArchitecture=MSIL" />
<Reference Include="nunit.framework, Version=2.6.0.12054, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\packages\NUnit.2.6.0.12054\lib\nunit.framework.dll</HintPath>
@@ -65,6 +66,7 @@
<Compile Include="IOTests.cs" />
<Compile Include="LazyTests.cs" />
<Compile Include="NonEmptyListTests.cs" />
+ <Compile Include="RoseTreeTests.cs" />
<Compile Include="StringsTests.cs" />
<Compile Include="Customer.cs" />
<Compile Include="DictionaryTests.cs" />
@@ -0,0 +1,98 @@
+using System;
+using System.Linq;
+using FSharpx.DataStructures;
+using Microsoft.FSharp.Collections;
+using NUnit.Framework;
+
+namespace FSharpx.CSharpTests {
+ [TestFixture]
+ public class RoseTreeTests {
+ [Test]
+ public void Create() {
+ // without sugar
+ var a = new RoseTree<int>(1, LazyListModule.ofArray(new[] {
+ new RoseTree<int>(2, LazyListModule.empty<RoseTree<int>>()),
+ }));
+
+ // with sugar (but no laziness)
+ var b = RoseTree.Create(1, RoseTree.Create(2));
+
+ Assert.AreEqual(b, a);
+ }
+
+ [Test]
+ public void Select() {
+ var b = RoseTree.Create(1, RoseTree.Singleton(2));
+ var c = from i in b select i + 1;
+ var d = RoseTree.Create(2, RoseTree.Singleton(3));
+ Assert.AreEqual(d, c);
+ }
+
+ [Test]
+ public void SelectMany() {
+ var b = RoseTree.Create(1, RoseTree.Singleton(2));
+ var c = b.SelectMany(i => {
+ if (i <= 1)
+ return RoseTree.Singleton(i);
+ return RoseTree.Create(i, RoseTree.Singleton(i+1));
+ });
+ PrintTree(c, 0);
+ var d = RoseTree.Create(1, RoseTree.Create(2, RoseTree.Singleton(3)));
+ Assert.AreEqual(d, c);
+ }
+
+ [Test]
+ public void SelectMany2() {
+ // kind of useless?
+ var b = RoseTree.Create(1, RoseTree.Singleton(2));
+ var c = b.SelectMany(RoseTree.Singleton, (x,y) => y);
+ PrintTree(c, 0);
+ var d = RoseTree.Create(1,
+ RoseTree.Singleton(2),
+ RoseTree.Create(1, RoseTree.Singleton(2)));
+ Assert.AreEqual(d, c);
+ }
+
+ [Test]
+ public void SelectManyLinq() {
+ // kind of useless?
+ var b = RoseTree.Create(1, RoseTree.Singleton(2));
+ var c = from i in b
+ let r = i <= 1 ? RoseTree.Singleton(i) : RoseTree.Create(i, RoseTree.Singleton(i + 1))
+ from j in r
+ select j;
+ PrintTree(c, 0);
+ var d = RoseTree.Create(1,
+ RoseTree.Create(2, RoseTree.Create(3)),
+ RoseTree.Create(1,
+ RoseTree.Create(2, RoseTree.Create(3))));
+ Assert.AreEqual(d, c);
+ }
+
+ private static RoseTree<T> R<T>(T root, params RoseTree<T>[] children) {
+ return RoseTree.Create(root, children);
+ }
+
+ [Test]
+ public void DFS() {
+ var a = R("f",
+ R("b",
+ R("a"),
+ R("d",
+ R("c"),
+ R("e"))),
+ R("g",
+ R("i",
+ R("h"))));
+ var elements = a.DfsPre().ToList();
+ CollectionAssert.AreEqual(new[] {"f", "b", "a", "d","c","e","g","i","h"}, elements);
+ }
+
+ private static void PrintTree<T>(RoseTree<T> tree, int level) {
+ var tabs = new string('\t', level);
+ Console.WriteLine(tabs + tree.Root);
+ foreach (var c in tree.Children)
+ PrintTree(c, level + 1);
+ }
+ }
+}

0 comments on commit 46b510e

Please sign in to comment.