Last active
February 22, 2023 08:27
-
-
Save savaged/d229dcefda0659d60f54ea4468f6cfea to your computer and use it in GitHub Desktop.
FP styled C# example inspired by Isaac Abraham's book Programming With F#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Unit = System.ValueTuple; | |
_ = App.Run(Console.WriteLine); | |
static class App | |
{ | |
public static Unit Run(Action<string> outputter) | |
{ | |
outputter(GetAwayWins().ToSummary()); | |
return Unit.Create(); | |
} | |
static IList<FootballTeamWinSummary> GetAwayWins() => | |
SampleDataset.Results.GetAwayWins(); | |
} | |
static class Extensions | |
{ | |
public static IList<FootballTeamWinSummary> GetAwayWins( | |
this IEnumerable<FootballGameResult> self) => | |
self.Where(r => r.IsAwayWin()) | |
.GroupBy( | |
r => r.AwayTeamResult.TeamName, | |
r => r, | |
(t, g) => new FootballTeamWinSummary(t, g.Count())) | |
.OrderBy(s => s.TeamName) | |
.ToList(); | |
public static bool IsAwayWin(this FootballGameResult self) => | |
self.AwayTeamResult.Goals > self.HomeTeamResult.Goals; | |
public static string ToSummary(this FootballTeamResult self) => | |
$"{self.TeamName}: {self.Goals}"; | |
public static string ToSummary(this IList<FootballTeamWinSummary> self) => | |
SummariseWins(self); | |
private static string SummariseWins( | |
IList<FootballTeamWinSummary> w, int i = 0, string s = "") | |
{ | |
if (w.TryGetNonEnumeratedCount(out int count) && count <= i) | |
return s; | |
s += $"{w[i].TeamName}: {w[i].Wins}{Environment.NewLine}"; | |
return SummariseWins(w, ++i, s); | |
} | |
} | |
record struct FootballTeamWinSummary(string TeamName, int Wins); | |
record struct FootballTeamResult(string TeamName, int Goals); | |
record struct FootballGameResult( | |
FootballTeamResult HomeTeamResult, FootballTeamResult AwayTeamResult); | |
static class SampleDataset | |
{ | |
public static IEnumerable<FootballGameResult> Results => | |
new List<FootballGameResult> | |
{ | |
new FootballGameResult( | |
new FootballTeamResult("Middlesbrough", 1), | |
new FootballTeamResult("Hull City", 2)), | |
new FootballGameResult( | |
new FootballTeamResult("Middlesbrough", 1), | |
new FootballTeamResult("Huddersfield Town", 3)), | |
new FootballGameResult( | |
new FootballTeamResult("Huddersfield Town", 3), | |
new FootballTeamResult("Hull City", 1)), | |
new FootballGameResult( | |
new FootballTeamResult("Huddersfield Town", 2), | |
new FootballTeamResult("Middlesbrough", 1)), | |
new FootballGameResult( | |
new FootballTeamResult("Hull City", 4), | |
new FootballTeamResult("Middlesbrough", 2)), | |
new FootballGameResult( | |
new FootballTeamResult("Hull City", 1), | |
new FootballTeamResult("Huddersfield Town", 2)), | |
}; | |
} |
SQL (MySQL 8.0) version gives all the clues to how simple a declarative style can be
DROP TEMPORARY TABLE IF EXISTS tmp;
CREATE TEMPORARY TABLE tmp
(
hometeam VARCHAR(50) NOT NULL,
homegoals INT NOT NULL,
awayteam VARCHAR(50) NOT NULL,
awaygoals INT NOT NULL
);
INSERT INTO tmp
(hometeam, homegoals, awayteam, awaygoals)
VALUES
('Middlesbrough', 1, 'Hull City', 2),
('Middlesbrough', 1, 'Huddersfield Town', 3),
('Huddersfield Town', 3, 'Hull City', 1),
('Huddersfield Town', 2, 'Middlesbrough', 1),
('Hull City', 4, 'Middlesbrough', 2),
('Hull City', 1, 'Huddersfield Town', 2);
SELECT
awayteam,
COUNT(*) AS wins
FROM tmp
WHERE awaygoals > homegoals
GROUP BY awayteam
ORDER BY wins;
DROP TEMPORARY TABLE tmp;
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
F# version (please remember I'm an FP noob)