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 + -