Exercise from https://github.com/DrBoolean/mostly-adequate-guide
source https://nuget.org/api/v2
nuget Newtonsoft.Json
open System
let maybe x f = function
| None -> x
| Some value -> f value
type Either<'a,'b> =
| Right of 'a
| Left of 'b
module Either =
let map (f: 'a -> 'b) e=
match e with
| Right a -> Right (f a)
| Left b -> Left b
let unwrap f g = function
| Left a -> f a
| Right b -> g b
let getAge (now: DateTimeOffset) birthdate =
let valid, date = DateTimeOffset.TryParse birthdate
if valid
then Right (now.Year - date.Year)
else Left "Birth date could not be parsed"
let inline toString x = x.ToString()
//printfn "%A" (getAge DateTimeOffset.Now "2005-12-12")
//printfn "%A" (getAge DateTimeOffset.Now "20010704")
let fortune = ((+)1) >> toString >> ((+) "If you survive, you will be ")
let zoltar = (getAge DateTimeOffset.Now) >> (Either.unwrap id fortune) >> (printfn "%s")
//printfn "%A" (zoltar "2005-12-12")
//printfn "%A" (zoltar "balloons!")
module Storage =
open System.Collections.Generic
let private storage = Dictionary<string,string>()
let getFromStorage key = fun () -> storage.[key]
type IO<'T> = { io: 'T }
module IO =
let wrap f = { io = f }
let from x = { io = fun () -> x }
let map f x = { io = f << x.io }
let run x = x.io()
let split (ch: char) (s: string) = s.Split ch
let path = IO.wrap <| fun () -> System.Environment.GetEnvironmentVariable "PATH"
let toArray = split ';'
let listPath = path |> IO.map (toArray >> Array.sort)
// printfn "%A" (IO.run listPath)
#load "task.fs"
open System.IO
open System.Threading.Tasks
open Folktale
let readFile (filename: string) =
Task.wrap <| fun (reject, resolve) ->
try
let reader = new StreamReader(filename)
reader.ReadToEndAsync()
.ContinueWith(fun (t: Task<string>) ->
if t.IsFaulted then reject (t.Exception.Flatten() :> Exception) else resolve t.Result
reader.Dispose())
|> ignore
with
| _ as ex -> reject ex
let x = readFile "paket.lock"
|> Task.map (split('\n'))
|> Task.map (Array.head)
let y = Task.from<unit,int> 3
|> Task.map ((+) 1)
x |> Task.fork (printfn "%A", printfn "%s")
y |> Task.fork (id, printfn "value = %d")
#r "packages/Newtonsoft.Json/lib/net45/Newtonsoft.Json.dll"
open System
open System.Net
open System.Threading.Tasks
open System.IO
open Newtonsoft.Json.Linq
let inline trace tag x =
printfn "%A %A" tag x
let img = sprintf """<img src="%s" />"""
module Str =
let removeParentheses (s :string) = s.TrimEnd(')').TrimStart('(')
let toString x = x.ToString()
let join delimiter (xs :string seq) = String.Join(delimiter, xs)
module Json =
let array property (o :JObject) = o.[property] :?> JArray
let obj property (o:JObject) = o.[property] :?> JObject
let value<'a> property (o :JObject) = o.[property].Value<'a>()
let toObj (tok :JToken) = tok :?> JObject
module Impure =
let getJSON callback (url :string) =
let http = WebRequest.Create url :?> HttpWebRequest
http.Accept <- "application/json"
http.MaximumAutomaticRedirections <- 4
let response = http.GetResponseAsync()
let handler (t :WebResponse Task) :unit =
use res = t.Result :?> HttpWebResponse
use reader = new StreamReader(res.GetResponseStream())
(callback << JObject.Parse << Str.removeParentheses << reader.ReadToEnd)()
response.ContinueWith handler :> Task |> Async.AwaitTask
let saveHtml file content = File.WriteAllText(file, content)
let url = sprintf "https://api.flickr.com/services/feeds/photos_public.gne?tags=%s&format=json&jsoncallback=?"
let mediaUrl = Json.obj "media" >> Json.value<string> "m"
let mediaToImg :JToken -> string = Json.toObj >> mediaUrl >> img
let images :JObject -> string seq = Json.array "items" >> Seq.map mediaToImg
let saveImages :JObject -> unit = images >> Str.join "\r\n" >> sprintf "<html><body>%s</body></html>" >> Impure.saveHtml "pictures.html"
let app = (Impure.getJSON saveImages) << url
app "piggy"
|> Async.RunSynchronously
let flip f a b = f b a
type Car = {
name: string
horsepower: int
dollar_value: double
in_stock: bool
}
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Car =
let name car = car.name
let in_stock car = car.in_stock
let dollar_value car = car.dollar_value
let horsepower car = car.horsepower
let CARS = [
{name= "Ferrari FF"; horsepower= 660; dollar_value= 700000.; in_stock= true}
{name= "Spyker C12 Zagato"; horsepower= 650; dollar_value= 648000.; in_stock= false}
{name= "Jaguar XKR-S"; horsepower= 550; dollar_value= 132000.; in_stock= false}
{name= "Audi R8"; horsepower= 525; dollar_value= 114200.0; in_stock= false}
{name= "Aston Martin One-77"; horsepower= 750; dollar_value= 1850000.0; in_stock= true}
{name= "Pagani Huayra"; horsepower= 700; dollar_value= 1300000.0; in_stock= false}
]
module re =
open System.Text.RegularExpressions
let ex s = Regex s
let replace (r :Regex) (replacement :string) (what :string) = r.Replace(what, replacement)
let isLastInStock :Car seq -> bool = Car.in_stock << Seq.last
printfn "Exercise 1: %A" <| isLastInStock CARS
let nameOfFirstCar :Car seq -> string = Seq.head >> Car.name
printfn "Exercise 2: %s" <| nameOfFirstCar CARS
let _average (xs :double list) = (xs |> List.reduce (+)) / double(List.length xs)
let averageDollarValue = _average << List.map Car.dollar_value
printfn "Exercise 3: %.2f" <| averageDollarValue CARS
let _underscore = re.replace (re.ex @"\W+") "_"
let sanitizeNames = List.map _underscore
printfn "Exercise 4: %A" <| sanitizeNames ["Hello world"]
let fastestCar :Car seq -> string = Seq.sortBy Car.horsepower >> Seq.last >> Car.name >> (flip (+) <| " is the fastest")
printfn "Exercise 5: %s" <| fastestCar CARS