type CheckNumber = int
type CardNumber = string
type CardType = Visa | Mastercard
type CreditCardInfo = CardType * CardNumber
type PaymentMethod =
| Cash
| Check of CheckNumber
| Card of CreditCardInfo
type PaymentAmount = decimal
type Currency = EUR | USD
type Payment = {
Amount : PaymentAmount
Currency: Currency
Method: PaymentMethod
// Card Game Example
type Suit = Club | Diamond | Spade | Heart
type Rank = Two | Three | Four | Five | Six | Seven | Eight
| Nine | Ten | Jack | Queen | King | Ace
type Card = Suit * Rank
type Hand = Card list
type Deck = Card list
type Player = { Name: string; Hand: Hand }
type Game = { Deck: Deck; Players: Player list }
type Deal = Deck -> Deck * Card
type PickUp = (Hand * Card) -> Hand
let add1 x = x + 1
let double x = x * 2
let square x = x * x
// 1. Show composition
let add1_double_square = add1 >> double >> square
// 2. Show piping
5 add1 |> double |> square
// 3. Show abstraction (if time)
let foo x = String.replicate x "X"
let bar s = String.length s
// abstracting away the string
let foo_bar = foo >> bar
void Main()
{
Func<int, int> add1 = x => x + 1;
Func<int, int> doubl = x => x * 2;
Func<int, int> square = x => x * x;
var add1_doubl_square = add1.Compose(doubl).Compose(square);
add1_doubl_square(5).Pipe(Console.WriteLine);
5.Pipe(add1).Pipe(doubl).Pipe(square).Pipe(Console.WriteLine);
}
public static class FuncExtensions
{
public static Func<T, V> Compose<T,U,V>(
this Func<T,U> left,
Func<U, V> right) => x => right(left(x));
public static U Pipe<T,U>(this T x, Func<T, U> f) => f(x);
public static void Pipe<T>(this T x, Action<T> f) => f(x);
}
You will need to install nuget packages FSharp.Data
and Suave
and reference the correct paths to their dlls.
#r "../packages/FSharp.Data/lib/net45/FSharp.Data.dll"
open FSharp.Data
type Species = HtmlProvider<"http://en.wikipedia.org/wiki/The_world's_100_most_threatened_species">
let species =
[ for x in Species.GetSample().Tables.``Species list``.Rows ->
x.Type, x.``Common name`` ]
let speciesSorted =
species
|> List.countBy fst
|> List.sortByDescending snd
#r "../packages/Suave/lib/net461/Suave.dll"
open Suave
let html =
[ yield "<html><body><ul>"
for (category, count) in speciesSorted do
yield sprintf "<li>Category <b>%s</b>: <b>%d</b></li>" category count
yield "</ul></body></html>" ]
|> String.concat "\n"
startWebServer defaultConfig (Successful.OK html)
open System
type ParserResult<'T> =
| Success of 'T * char list
| Failure
type Parser<'T> = char list -> ParserResult<'T>
let run parser (input: string) =
let stream = input |> Seq.toList
match parser stream with
| Success (v, rest) -> printfn "Parsed '%s': '%A' leaving '%s'" input v (String(List.toArray rest))
| Failure -> printfn "Failed to parse '%s'" input
let CharParser c =
fun stream ->
match stream with
| x :: xs when x = c -> Success (c, xs)
| _ -> Failure
let (<|>) p1 p2 =
fun stream ->
match p1 stream with
| Failure -> p2 stream
| x -> x
let DigitParser =
['0'..'9']
|> List.map CharParser
|> List.reduce (<|>)
let (|>>) p f =
fun stream ->
match p stream with
| Success (v, rest) -> Success (f v, rest)
| Failure -> Failure
let DigitParserInt =
DigitParser |>> (fun v -> int v - int '0')
let rec Many p =
fun stream ->
match p stream with
| Failure -> Success ([], stream)
| Success (v, rest) -> (Many p) |>> (fun w -> v :: w) <| rest
let Many1 p =
fun stream ->
match p stream with
| Failure -> Failure
| Success (v, rest) -> (Many p) |>> (fun w -> v :: w) <| rest
let IntegerParser =
(Many1 DigitParserInt)
|>> List.reduce (fun x y -> 10 * x + y)
let (>>.) p1 p2 =
fun stream ->
match p1 stream with
| Failure -> Failure
| Success (_, rest) -> p2 rest
let StringParser (str: string) =
str.ToCharArray()
|> Array.map CharParser
|> Array.reduce (>>.)
|>> (fun _ -> str)
let (.>>) p1 p2 =
fun stream ->
match p1 stream with
| Success (v, rest) -> p2 |>> (fun _ -> v) <| rest
| Failure -> Failure
let eof =
fun stream ->
match stream with
| [] -> Success ((), stream)
| _ -> Failure
let StudentIdParser =
StringParser "SID" >>. IntegerParser .>> eof
run StudentIdParser "SID1234"
let numeralsMap =
[ 1000, "M"
900, "CM"
500, "D"
400, "CD"
100, "C"
90, "XC"
50, "L"
40, "XL"
10, "X"
9, "IX"
5, "V"
4, "IV"
1, "I" ]
let rec arabicToRoman num =
match num with
| 0 -> ""
| _ ->
let picker (value, roman) =
if value <= num
then Some (value, roman)
else None
let (value, roman) = List.pick picker numeralsMap
roman + (arabicToRoman (num - value))
printfn "%s" (arabicToRoman 8)