diff --git a/.gitignore b/.gitignore
index 749d8819..901719da 100755
--- a/.gitignore
+++ b/.gitignore
@@ -1,9 +1,4 @@
-FSharpKoans.Core/bin/
-FSharpKoans.Core/obj/
-FSharpKoans/bin/
-FSharpKoans/obj/
-FSharpKoans.Test/bin/
-FSharpKoans.Test/obj/
-FSharpKoans2008.suo
-FSharpKoans2010.suo
+[Bb]in/
+[Oo]bj/
+*.suo
packages/
diff --git a/FSharpKoans.Core/FsharpKoans.Core.fsproj b/FSharpKoans.Core/FsharpKoans.Core.fsproj
index 78ab2fcb..f9ddd647 100755
--- a/FSharpKoans.Core/FsharpKoans.Core.fsproj
+++ b/FSharpKoans.Core/FsharpKoans.Core.fsproj
@@ -14,6 +14,8 @@
..\
+ 4.3.0.0
+ 11
true
@@ -34,9 +36,19 @@
3
bin\Release\FSharpKoans.Core.XML
-
-
-
+
+
+
+ $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets
+
+
+
+
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets
+
+
+
+
@@ -46,8 +58,10 @@
+
+ True
+
-
..\packages\NUnit.2.5.10.11092\lib\nunit.framework.dll
True
@@ -71,4 +85,4 @@
-->
-
+
\ No newline at end of file
diff --git a/FSharpKoans.Test/FSharpKoans.Test.fsproj b/FSharpKoans.Test/FSharpKoans.Test.fsproj
index eae391e0..0ffb1881 100755
--- a/FSharpKoans.Test/FSharpKoans.Test.fsproj
+++ b/FSharpKoans.Test/FSharpKoans.Test.fsproj
@@ -12,6 +12,8 @@
v4.0
FSharpKoans.Test
..\
+ 4.3.0.0
+ 11
true
@@ -32,9 +34,19 @@
3
bin\Release\FSharpKoans.Test.XML
-
-
-
+
+
+
+ $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets
+
+
+
+
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets
+
+
+
+
@@ -42,8 +54,10 @@
+
+ True
+
-
..\packages\NUnit.2.5.10.11092\lib\nunit.framework.dll
True
@@ -74,4 +88,4 @@
-->
-
+
\ No newline at end of file
diff --git a/FSharpKoans.sln b/FSharpKoans.sln
index 42af5953..7f4af7e6 100755
--- a/FSharpKoans.sln
+++ b/FSharpKoans.sln
@@ -1,6 +1,8 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2012
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FsharpKoans.Core", "FSharpKoans.Core\FsharpKoans.Core.fsproj", "{71460AA5-7357-4F1C-99BC-54244B50B00E}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharpKoans", "FSharpKoans\FSharpKoans.fsproj", "{87C025E8-3E63-4A20-B1CA-2E346D0E0C51}"
@@ -19,18 +21,6 @@ Global
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {69F00CBF-0EDC-4260-B852-C53B8C44BBCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {69F00CBF-0EDC-4260-B852-C53B8C44BBCE}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {69F00CBF-0EDC-4260-B852-C53B8C44BBCE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {69F00CBF-0EDC-4260-B852-C53B8C44BBCE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {69F00CBF-0EDC-4260-B852-C53B8C44BBCE}.Debug|x64.ActiveCfg = Debug|Any CPU
- {69F00CBF-0EDC-4260-B852-C53B8C44BBCE}.Debug|x86.ActiveCfg = Debug|Any CPU
- {69F00CBF-0EDC-4260-B852-C53B8C44BBCE}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {69F00CBF-0EDC-4260-B852-C53B8C44BBCE}.Release|Any CPU.Build.0 = Release|Any CPU
- {69F00CBF-0EDC-4260-B852-C53B8C44BBCE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {69F00CBF-0EDC-4260-B852-C53B8C44BBCE}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {69F00CBF-0EDC-4260-B852-C53B8C44BBCE}.Release|x64.ActiveCfg = Release|Any CPU
- {69F00CBF-0EDC-4260-B852-C53B8C44BBCE}.Release|x86.ActiveCfg = Release|Any CPU
{71460AA5-7357-4F1C-99BC-54244B50B00E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{71460AA5-7357-4F1C-99BC-54244B50B00E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{71460AA5-7357-4F1C-99BC-54244B50B00E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -55,6 +45,18 @@ Global
{87C025E8-3E63-4A20-B1CA-2E346D0E0C51}.Release|x64.ActiveCfg = Release|x86
{87C025E8-3E63-4A20-B1CA-2E346D0E0C51}.Release|x86.ActiveCfg = Release|x86
{87C025E8-3E63-4A20-B1CA-2E346D0E0C51}.Release|x86.Build.0 = Release|x86
+ {69F00CBF-0EDC-4260-B852-C53B8C44BBCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {69F00CBF-0EDC-4260-B852-C53B8C44BBCE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {69F00CBF-0EDC-4260-B852-C53B8C44BBCE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {69F00CBF-0EDC-4260-B852-C53B8C44BBCE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {69F00CBF-0EDC-4260-B852-C53B8C44BBCE}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {69F00CBF-0EDC-4260-B852-C53B8C44BBCE}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {69F00CBF-0EDC-4260-B852-C53B8C44BBCE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {69F00CBF-0EDC-4260-B852-C53B8C44BBCE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {69F00CBF-0EDC-4260-B852-C53B8C44BBCE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {69F00CBF-0EDC-4260-B852-C53B8C44BBCE}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {69F00CBF-0EDC-4260-B852-C53B8C44BBCE}.Release|x64.ActiveCfg = Release|Any CPU
+ {69F00CBF-0EDC-4260-B852-C53B8C44BBCE}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/FSharpKoans/AboutFiltering.fs b/FSharpKoans/AboutFiltering.fs
new file mode 100644
index 00000000..a668a870
--- /dev/null
+++ b/FSharpKoans/AboutFiltering.fs
@@ -0,0 +1,121 @@
+namespace FSharpKoans
+open FSharpKoans.Core
+
+module NumberFilterer =
+
+ let someIfPositive x =
+ if x % 2 = 0 then Some x
+ else None
+
+//---------------------------------------------------------------
+// Getting Started with Filtering Lists
+//
+// Lists in F# can be filtered in a number of ways.
+// This koan looks at:
+// - filter
+// - find / tryFind
+// - choose
+// - pick
+//---------------------------------------------------------------
+
+[]
+module ``about filtering`` =
+ open NumberFilterer
+
+ []
+ let FilteringAList() =
+ let names = [ "Alice"; "Bob"; "Eve"; ]
+
+ // Find all the names starting with "A" using an anonymous function
+ let actual_names =
+ names
+ |> List.filter (fun name -> name.StartsWith( "A" ))
+
+ AssertEquality actual_names [ __ ]
+
+ //Or passing a function to filter
+ let startsWithTheLetterB (s: string) =
+ s.StartsWith("B")
+
+ let namesBeginningWithB =
+ names
+ |> List.filter startsWithTheLetterB
+
+ AssertEquality namesBeginningWithB [ __ ]
+
+ []
+ let FindingJustOneItem() =
+ let names = [ "Alice"; "Bob"; "Eve"; ]
+ let expected_name = "Bob"
+
+ // find will return just one item, or throws an exception
+
+ let actual_name =
+ names
+ |> List.find (fun name -> name = __ )
+
+ //??? What would happen if there are 2 Bob's in the List?
+
+ AssertEquality expected_name actual_name
+
+ []
+ let FindingJustOneOrZeroItem() =
+ let names = [ "Alice"; "Bob"; "Eve"; ]
+
+ // tryFind returns an option so you can handle 0 rows returned
+ let eve =
+ names
+ |> List.tryFind (fun name -> name = "Eve" )
+ let zelda =
+ names
+ |> List.tryFind (fun name -> name = "Zelda" )
+
+ AssertEquality eve.IsSome __
+ AssertEquality zelda.IsSome __
+
+ []
+ let ChoosingItemsFromAList() =
+ let numbers = [ 1; 2; 3; ]
+
+ // choose takes a function that transforms the input into an option
+ // And filters out the results that are None.
+ let positiveNumbers =
+ numbers
+ |> List.choose someIfPositive
+
+ AssertEquality positiveNumbers [ __ ]
+
+ //You can also use the "id" function on types of 'a option list
+ //"id" will tell choose only to return just those that are "Some"
+ let optionNames = [ None; Some "Alice"; None; ]
+
+ let namesWithValue =
+ optionNames
+ |> List.choose id
+
+ //Notice the type of actual result is 'string list', where as optionNumbers is 'string option list'
+ AssertEquality namesWithValue [ __ ]
+
+ []
+ let PickingItemsFromAList() =
+ let numbers = [ 5..10 ]
+
+ //Pick is similar to choose, but returns the first element, or throwns an exception if are no
+ //items that return "Some" (a bit like find does)
+ let firstEvenPositive =
+ numbers
+ |> List.pick someIfPositive
+
+ AssertEquality firstEvenPositive __
+
+ //As with choose, you can also use the "id" function on types of 'a option list
+ //to return just those that are "Some"
+ let optionNames = [ None; Some "Alice"; None; Some "Bob"; ]
+
+ let firstNameWithValue =
+ optionNames
+ |> List.pick id
+
+ AssertEquality firstNameWithValue __
+
+ //There is also a tryPick which works like tryFind, returning "None" instead of throwing an exception.
diff --git a/FSharpKoans/FSharpKoans.fsproj b/FSharpKoans/FSharpKoans.fsproj
index fe7d7a16..c367c41d 100755
--- a/FSharpKoans/FSharpKoans.fsproj
+++ b/FSharpKoans/FSharpKoans.fsproj
@@ -14,6 +14,8 @@
FSharpKoans
..\
+ 4.3.0.0
+ 11
true
@@ -37,9 +39,19 @@
x86
bin\Release\FSharpKoans1.XML
-
-
-
+
+
+
+ $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets
+
+
+
+
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets
+
+
+
+
@@ -64,14 +76,17 @@
+
Always
+
+ True
+
-