diff --git a/FSharpKoans.Core/KoanContainer.fs b/FSharpKoans.Core/KoanContainer.fs index cfd4b795..8259159b 100755 --- a/FSharpKoans.Core/KoanContainer.fs +++ b/FSharpKoans.Core/KoanContainer.fs @@ -21,7 +21,12 @@ let runKoans container = with | ex -> let outcome = sprintf "%s failed." m.Name - Failure(outcome, ex.InnerException) + let ex = + match ex.InnerException with + | null -> Some(ex) + | _ -> Some(ex.InnerException) + + Failure(outcome, ex) container |> findKoanMethods diff --git a/FSharpKoans.Core/KoanResult.fs b/FSharpKoans.Core/KoanResult.fs index a6405e1f..9ddfbeb3 100755 --- a/FSharpKoans.Core/KoanResult.fs +++ b/FSharpKoans.Core/KoanResult.fs @@ -4,7 +4,7 @@ open System type KoanResult = | Success of string - | Failure of string * Exception + | Failure of string * Option with member this.Message = match this with diff --git a/FSharpKoans.Test/RunningKoans.fs b/FSharpKoans.Test/RunningKoans.fs old mode 100755 new mode 100644 index 1b9eaeee..3ad8d9a3 --- a/FSharpKoans.Test/RunningKoans.fs +++ b/FSharpKoans.Test/RunningKoans.fs @@ -37,13 +37,14 @@ let ``A failing koan returns its exception`` () = typeof |> KoanContainer.runKoans |> Seq.head - - let ex = + + let msg = match result with - | Failure (_, ex) -> ex - | _ -> null + | Failure (_, Some(ex)) -> ex.Message + | Failure (_, None) -> "No Exception!" + | Success (s) -> s - Assert.AreEqual("expected failure", ex.Message) + Assert.AreEqual("expected failure", msg) [] let ``A failing koan returns a failure message`` () = diff --git a/FSharpKoans/AboutTypeProviders.fs b/FSharpKoans/AboutTypeProviders.fs index 37d6b6d5..803ee99d 100644 --- a/FSharpKoans/AboutTypeProviders.fs +++ b/FSharpKoans/AboutTypeProviders.fs @@ -8,6 +8,18 @@ open FSharpKoans.Core // F# Type Providers make things like processing data from a // variety of providers easily done in a typed fashion. // +// Type Providers Available +// * DbmlFile - http://msdn.microsoft.com/en-us/library/hh362326.aspx +// * EdmxFile - http://msdn.microsoft.com/en-us/library/hh362313.aspx +// * ODataService - http://msdn.microsoft.com/en-us/library/hh362325.aspx +// * SqlDataConnection - http://msdn.microsoft.com/en-us/library/hh362320.aspx +// * SqlEntityConnection - http://msdn.microsoft.com/en-us/library/hh362322.aspx +// * WsdlService - http://msdn.microsoft.com/en-us/library/hh362328.aspx +// * CSV - http://fsharp.github.io/FSharp.Data/library/CsvProvider.html +// * HTML - http://fsharp.github.io/FSharp.Data/library/HtmlProvider.html +// * JSON - http://fsharp.github.io/FSharp.Data/library/JsonProvider.html +// * XML - http://fsharp.github.io/FSharp.Data/library/XmlProvider.html +// * WorldBank - http://fsharp.github.io/FSharp.Data/library/WorldBank.html // // For a more thorough introduction to TypeProviders // https://docs.microsoft.com/en-us/dotnet/fsharp/tutorials/type-providers/ @@ -16,36 +28,67 @@ open FSharpKoans.Core [] module ``about type providers`` = open FSharp.Data - open System.IO + open System.IO - type Simple = CsvProvider<"data/Simple.csv"> + type Simple = CsvProvider<"data/Stocks.csv"> - let getContent = - use file = File.OpenRead("data/Simple.csv") + let getCsvContent = + use file = File.OpenRead("data/Stocks.csv") Simple.Load(file).Rows - + |> Seq.toList // this is kind of a cheat to get around the fact that the stream needs to be closed [] let CountingLinesInACSV() = // you can count items with a sequence operation over the data let countOfItems = - getContent + getCsvContent |> Seq.length - AssertEquality countOfItems __ + AssertEquality countOfItems __ // fix this [] let GetCsvContentAndPerformAProjection() = - // you can do other transformations like projects in a typed fashion - let popularities = - getContent - |> Seq.map (fun x -> x.Popularity) - |> Seq.sort - |> Seq.toArray - - let sumOfPopularities = popularities |> Seq.sum - - AssertEquality sumOfPopularities __ - - AssertEquality popularities __ \ No newline at end of file + // try transformations like projections in a typed fashion with a simple predicate + // typed to the column name + let avgOpen = + getCsvContent + // What column makes this work? + |> Seq.averageBy ( fun x -> x.Open ) // write this projection + + AssertEquality 32.185217391304347826086956522m avgOpen + + [] + let RenameAColumnAndSeeACompileTimeBreak() = + // one of the benefits of type providers is that when the source changes, the compiler will tell you! + + let avgAdjClose = + getCsvContent + // Rename the CSV column "Adj Close" to "AdjustedClose" in data/Stocks.csv + // compile the code to see the code on the next line break + |> Seq.averageBy (fun x -> x.``Adj Close`` ) + + AssertEquality 32.175217391304347826086956522m avgAdjClose + + + type NugetStats = HtmlProvider<"https://www.nuget.org/packages/FSharp.Data"> + + // helper function to analyze version numbers from Nuget + let getMinorVersion (v:string) = + System.Text.RegularExpressions.Regex(@"\d.\d").Match(v).Value + + let getNugetStats = + NugetStats().Tables.``Version History``.Rows + + [] + let TypeProvidersExistForWebRequestsAsWell() = + // group by minor version and calculate download count + + let stats = + getNugetStats + |> Seq.groupBy (fun r -> + getMinorVersion r.Version) + |> Seq.map (fun (k, xs) -> + k, xs |> Seq.sumBy (fun x -> x.Downloads)) + + AssertEquality __ __ \ No newline at end of file diff --git a/FSharpKoans/FSharpKoans.fsproj b/FSharpKoans/FSharpKoans.fsproj index a547283c..34db8ee9 100644 --- a/FSharpKoans/FSharpKoans.fsproj +++ b/FSharpKoans/FSharpKoans.fsproj @@ -5,8 +5,8 @@ FSharpKoans - - Always + + Always @@ -32,8 +32,8 @@ - - + + diff --git a/FSharpKoans/PathToEnlightenment.fs b/FSharpKoans/PathToEnlightenment.fs index ceef9a84..52f1bd15 100755 --- a/FSharpKoans/PathToEnlightenment.fs +++ b/FSharpKoans/PathToEnlightenment.fs @@ -13,10 +13,16 @@ match result with printfn "" printfn "" printfn "You have not yet reached enlightenment ..." - printfn "%s" ex.Message + printfn "%s" + (match ex with + | None -> "No error message could be found!" + | Some(ex) -> ex.Message) printfn "" printfn "Please meditate on the following code:" - printfn "%s" ex.StackTrace + printfn "%s" + (match ex with + | None -> "No stack trace could be found!" + | Some(ex) -> ex.StackTrace) printfn "" printfn "" diff --git a/FSharpKoans/data/Simple.csv b/FSharpKoans/data/Simple.csv deleted file mode 100644 index d232e726..00000000 --- a/FSharpKoans/data/Simple.csv +++ /dev/null @@ -1,4 +0,0 @@ -Language, Popularity -F#, 2, -C#, 1, -VB.NET, 3 \ No newline at end of file diff --git a/FSharpKoans/data/Stocks.csv b/FSharpKoans/data/Stocks.csv new file mode 100644 index 00000000..cbdf4832 --- /dev/null +++ b/FSharpKoans/data/Stocks.csv @@ -0,0 +1,24 @@ +Date,Open,High,Low,Close,Volume,Adj Close +2012-03-30,32.40,32.41,32.04,32.26,31749400,32.26 +2012-03-29,32.06,32.19,31.81,32.12,37038500,32.12 +2012-03-28,32.52,32.70,32.04,32.19,41344800,32.19 +2012-03-27,32.65,32.70,32.40,32.52,36274900,32.52 +2012-03-26,32.19,32.61,32.15,32.59,36758300,32.59 +2012-03-23,32.10,32.11,31.72,32.01,35912200,32.01 +2012-03-22,31.81,32.09,31.79,32.00,31749500,32.00 +2012-03-21,31.96,32.15,31.82,31.91,37928600,31.91 +2012-03-20,32.10,32.15,31.74,31.99,41566800,31.99 +2012-03-19,32.54,32.61,32.15,32.20,44789200,32.20 +2012-03-16,32.91,32.95,32.50,32.60,65626400,32.60 +2012-03-15,32.79,32.94,32.58,32.85,49068300,32.85 +2012-03-14,32.53,32.88,32.49,32.77,41986900,32.77 +2012-03-13,32.24,32.69,32.15,32.67,48951700,32.67 +2012-03-12,31.97,32.20,31.82,32.04,34073600,32.04 +2012-03-09,32.10,32.16,31.92,31.99,34628400,31.99 +2012-03-08,32.04,32.21,31.90,32.01,36747400,32.01 +2012-03-07,31.67,31.92,31.53,31.84,34340400,31.84 +2012-03-06,31.54,31.98,31.49,31.56,51932900,31.56 +2012-03-05,32.01,32.05,31.62,31.80,45240000,31.80 +2012-03-02,32.31,32.44,32.00,32.08,47314200,32.08 +2012-03-01,31.93,32.39,31.85,32.29,77344100,32.29 +2012-02-29,31.89,32.00,31.61,31.74,59323600,31.74 \ No newline at end of file