Skip to content

Instantly share code, notes, and snippets.

@habib-sadullaev
Last active December 25, 2023 07:35
Show Gist options
  • Save habib-sadullaev/c9841d022c90aef327d7db9e8b1a0a1a to your computer and use it in GitHub Desktop.
Save habib-sadullaev/c9841d022c90aef327d7db9e8b1a0a1a to your computer and use it in GitHub Desktop.
type Tuple = Tuple with
static member inline TupleMap (Tuple, (a, b)) = fun f -> (f a, f b)
static member inline TupleMap (Tuple, (a, b, c)) = fun f -> (f a, f b, f c)
static member inline TupleMap (Tuple, (a, b, c, d)) = fun f -> (f a, f b, f c, f d)
let inline mapTuple f x =
let inline map (a: ^a) (b : ^b) = ((^a or ^b) : (static member TupleMap : ^a * ^b -> ^t) (a, b))
map Tuple x f
mapTuple (fun x -> x * x + 1) (1, 2)
mapTuple string (1, 2, 3)
mapTuple id (1, 2, 3, 4)
@habib-sadullaev
Copy link
Author

https://gist.github.com/Lanayx/18c21ea6319deb04be673e58958bca89

open Printf
open System
open System.Threading
open System.Text.RegularExpressions

type Response = 
    {
        Code: int
        Body: string
    }

     
let matchRoute (format: PrintfFormat<'a, unit, 'b, 'b>) (handler: 'a) =    
    let handlerType = handler.GetType()
    let handlerMethod = handlerType.GetMethods()[0]
    let mutable counter = 0
    let mutable replacedValue = format.Value
    replacedValue <- Regex("%d").Replace(replacedValue, fun _ -> $"(?<digits{Interlocked.Increment(&counter)}>\d+)")
    replacedValue <- Regex("%s").Replace(replacedValue, fun _ -> $"(?<letters{Interlocked.Increment(&counter)}>\w+)")
    let regex = Regex($"^{replacedValue}$")
    fun (url: string)  ->
        let m = regex.Match(url)
        if (m.Success) then            
            let result = 
                handlerMethod.Invoke(handler, ([| 
                    for g in m.Groups do 
                        if (g.Index) > 0 then
                            if g.Name.StartsWith("digits", StringComparison.Ordinal) then
                                int g.Value
                            else
                                g.Value
                |])) :?> 'b
            Some result
        else
            None


let myHandler1 (p1: int) (p2: int) =
    {
        Code = 200
        Body = sprintf "%d/%d" p1 p2
    }

let myHandler2 (p1: int) (p2: string) =
    {
        Code = 200
        Body = sprintf "%d/%s" p1 p2
    }
let myHandler3 (p1: int) =
    {
        Code = 200
        Body = sprintf "%d" p1
    }


let routes =
    seq {
        matchRoute "abc/%d/%d" myHandler1
        matchRoute "abc/%d/%s" myHandler2
        matchRoute "fff/%d" myHandler3
    }

let route url =
    routes 
    |> Seq.choose (fun checkRoute -> checkRoute url)
    |> Seq.tryHead
    |> Option.defaultValue { Code = 404; Body = "NotFound"}
    
//example usage
route "abc/1/abc" 

@habib-sadullaev
Copy link
Author

habib-sadullaev commented Dec 22, 2023

type Show =
    static member asString (x: int) : string = string x
    static member asString (x: double) : string = string x

let inline show x =
    let inline resolve (_: ^t) (x: ^x) = ((^t or ^x) : (static member asString: ^x -> string) x)
    resolve Unchecked.defaultof<Show> x

type Show with    
    static member inline asString (x: ^t option) : string =
        match x with
        | Some x -> show x
        | None -> ""

show 1 |> printfn "%s" 
show 2.9 |> printfn "%s"
show "3" |> printfn "%s"
show (Some 5) |> printfn "%s"
show (None: int option) |> printfn "%s"
show (Some 6L) |> printfn "%s" // error
show 1L |> printfn "%s" // error

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment