forth F#Applicative Functor

F#Applicative Functor

SeqApplicative.fs
// ref: http://bugsquash.blogspot.com/2010/12/zipping-with-applicative-functors-in-f.html
module SeqApplicative =
  let puree v = Seq.initInfinite (fun _ -> v)
  let (<*>) f a = Seq.zip f a |> Seq.map (fun (f', a') -> f' a')
  let (<!>) f a = puree f <*> a

forth 对有用的操作

对有用的操作

pair.js
// ES6
import R from 'ramda'

export function fst(a) { return a[0] }
export function snd(a) { return a[1] }
export function ofSame(a) { return [a,a] }
export function of(a,b) { return [a,b] }
export const map = R.curry(function PairsMap(f, a) {
  return [f(a[0]), f(a[1])]
})
export const apply = R.curry(function PairsApply(af, a){
  return [ af[0](a[0]), af[1](a[1]) ]
})
export const cross = R.curry(function PairsCross(a, x){
  return [ [a[0], x], [a[1],x ] ]
})
export function swap(a) { return [a[1], a[0]] }
export const fapply = R.curry(function FuncApply(af, x){
  return [ af[0](x), af[1](x) ]
})
export const pipe = R.curry(function PairsPipeCall(af, x){
  return af[1]( af[0] (x))
})
export const pipe2 = R.curry(function PairsPipeCall2(af, x){
  return af[1]( x, af[0] (x))
})
pair.fs
module RZ.Pair

let inline ofSame a = (a,a)
let inline of' a b = (a,b)
let inline with' b a = (a,b)
let inline sndWith a b = (a,b)
let inline call f (a,b) = f(a,b)
let inline map f (a,b) = (f a, f b)
let inline fapply (f,g) x = (f x, g x)
let inline cross (a,b) x = ((a,x), (b,x))
let inline pipe (g,f) x = f (g x)
let inline pipe2 (g,f) x = f x (g x)
let inline apply (f,g) (a,b) = (f a, g b)   (* applicative functor *)
let inline swap (a,b) = (b,a)

forth F#IO monad

F#IO monad

IO.fs
module RZ.Foundation.Monad

[<NoComparison; NoEquality>]
type IO<'T> = { io: unit -> 'T }

module IO =
  let inline wrap f = { io = f }
  let inline from x = { io = fun () -> x }
  let inline map f x = { io = f << x.io }
  let inline run x = x.io()

  let join = run
  let inline bind f = map f >> join

  type IOBuilder() =
    member self.Return x = from x

    member self.Bind(m, f) = m |> bind f
    member self.Delay restf = wrap (restf >> run)
    member self.TryWith (io, exnf) =
      wrap (fun() -> 
              try
                run io
              with
              | ex -> run (exnf ex))
    member self.Zero() = from ()

let io = IO.IOBuilder()

forth 字符串扩展名

字符串扩展名

iString.fs
module RZ.String

/// <summary>
/// Case-insensitive string
/// </summary>
type iString(s: string) =
  let normalized = s.ToLower(Globalization.CultureInfo.InvariantCulture)
  let ieq a b = System.String.Equals(a, b, StringComparison.OrdinalIgnoreCase)
  let icmp a b = System.String.Compare(s, b, StringComparison.OrdinalIgnoreCase)

  let eval def f (a: obj) =
    match a with
    | :? string as a_str -> f s a_str
    | :? iString as other -> f s other.Value
    | _ -> def()

  member x.Value = s

  override x.Equals(a) = eval (fun _ -> false) ieq a

  override x.GetHashCode() = normalized.GetHashCode()

  override x.ToString() = s

  interface IComparable with
    member x.CompareTo(a) = eval (fun _ -> raise <| ArgumentException(a.GetType().ToString())) icmp a

  member x.StartsWith other = s.StartsWith(other, StringComparison.OrdinalIgnoreCase)
  member x.Substring(start) = iString <| s.Substring(start)
  member x.IfBlank(new_s) = if String.IsNullOrEmpty s then iString new_s else x
  member x.map(f) = iString (f s)

  static member get (s: iString) = s.Value


[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module iString =
  let map f (s: iString) = s.map(f)
StringExtension.cs
using System;

namespace RZ.Extensions{
    public class NotNullableString : IComparable, IComparable<NotNullableString> {
        readonly string s;
        public NotNullableString(string s){
            if (s == null)
                throw new InvalidOperationException("String cannot be null!");
            this.s = s;
        }
        public override string ToString(){
            return s;
        }
        public override bool Equals(object o) {
            var anotherNS = o as NotNullableString;
            if (anotherNS != null)
                return anotherNS.s == s;
            else {
                var anotherS = o as string;
                return (anotherS != null) && anotherS == s;
            }
        }
        public override int GetHashCode() {
            return s.GetHashCode();
        }
        public int CompareTo(object obj){
            return s.CompareTo(obj);
        }

        public int CompareTo(NotNullableString other){
            return other.s.CompareTo(s);
        }

        static public implicit operator String(NotNullableString ns){
            return ns.s;
        }
        static public implicit operator NotNullableString(string s){
            return new NotNullableString(s);
        }
    }
    public static class StringExtension{
        static public string Apply<T>(this string s, T data){
            return String.Format(s, data);
        }
        static public string Apply<T, U>(this string s, T data, U o2) {
            return String.Format(s, data, o2);
        }
        static public string Apply<T, U, V>(this string s, T data, U o2, V o3) {
            return String.Format(s, data, o2, o3);
        }
    }
}
NBString.fs
module RZ.String

/// <summary>
/// New Non-blank string
/// </summary>
type NBString = NBString of string
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module NBString =
    let from s =
        if String.IsNullOrWhiteSpace s then invalidArg "s" "String cannot be blank or empty"
        NBString s
    let get (NBString s) = s

forth 'Vsync'(AKA,'变量同步')计算表达式,它同步到Sync comp中。 EXPR。当SYNC是#defined时,进入

'Vsync'(AKA,'变量同步')计算表达式,它同步到Sync comp中。 EXPR。当SYNC是#defined时,进入Async comp。 EXPR。除此以外。

Vsync.fs
namespace YourNamespaceHere
open System
open System.Diagnostics
open System.Threading
open System.Threading.Tasks

/// The 'Sync' builder for evaluating expressions in a synchronous style to aid debugging.
type [<Sealed>] Sync () =
    member inline this.Bind (x, f) = f x
    member inline this.Return x = x
    member inline this.ReturnFrom x = x
    member inline this.Zero () = ()
    member inline this.Combine ((), _) = ()
    member inline this.Yield x = x
    member inline this.YieldFrom x = x
    member inline this.Run f = f ()
    member inline this.Delay f = fun () -> f ()
    member inline this.For (s, f) = for x in s do f x
    member inline this.While (g, b) = while g () do this.Run b
    member inline this.TryWith (b, h) = try this.Run b with exn -> h exn
    member inline this.TryFinally (b, c) = try this.Run b finally c ()
    member inline this.Using (d, b) = use u = d in b u
    static member inline Ignore _ = ()
    static member inline Sleep (t : int) = Thread.Sleep t
    static member inline RunSynchronously x = x
    static member inline Start x = x
    static member inline StartAsTask x : _ Task = Task.Factory.StartNew (fun () -> x)
    static member inline AwaitTask (t : _ Task) = t.Result
    static member inline Catch x = Choice1Of2 x
    static member inline Parallel (s : _ seq) = s |> Seq.map (fun x -> Thread.Sleep 10; x) |> List.ofSeq |> Seq.ofList // Thread.Sleep keeps from soaking CPU

[<AutoOpen; CompilationRepresentation (CompilationRepresentationFlags.ModuleSuffix)>]
module Sync =

    /// The Sync builder instance.
    /// Used like: sync { return 0 }
    let sync = Sync ()

/// The 'Vsync' (AKA, 'Variable Synchronization') cexpr that coheres into the Sync cexpr when SYNC is #defined, and
/// into the Async cexpr otherwise.
/// TODO: forward documentation from FSharp.Core.
type [<Sealed>] Vsync () =

    member inline this.Builder =
#if SYNC
        sync
#else
        async
#endif

    member inline this.Bind (m, f) = this.Builder.Bind (m, f)
    member inline this.Return x = this.Builder.Return x
    member inline this.ReturnFrom m = this.Builder.ReturnFrom m
    member inline this.Zero () = this.Builder.Zero ()
    member inline this.Combine (a, b) = this.Builder.Combine (a, b)
#if SYNC
    member inline this.Yield x = this.Builder.Yield x
    member inline this.YieldFrom x = this.Builder.YieldFrom x
    member inline this.Run f = this.Builder.Run f
#endif
    member inline this.Delay f = this.Builder.Delay f
    member inline this.For (m, f) = this.Builder.For (m, f)
    member inline this.While (g, b) = this.Builder.While (g, b)
    member inline this.TryWith (b, h) = this.Builder.TryWith (b, h)
    member inline this.TryFinally (b, c) = this.Builder.TryFinally (b, c)
    member inline this.Using (d, b) = this.Builder.Using (d, b)

    static member inline Ignore m =
#if SYNC
        Sync.Ignore m
#else
        Async.Ignore m
#endif

    static member inline Sleep t =
#if SYNC
        Sync.Sleep t
#else
        Async.Sleep t
#endif

    static member inline RunSynchronously m =
#if SYNC
        Sync.RunSynchronously m
#else
        Async.RunSynchronously m
#endif

    static member inline Start m =
#if SYNC
        Sync.Start m
#else
        Async.Start m
#endif

    static member inline StartAsTask m : _ Task =
#if SYNC
        Sync.StartAsTask m
#else
        Async.StartAsTask m
#endif

    static member inline AwaitTask (t : _ Task) =
#if SYNC
        Sync.AwaitTask t
#else
        Async.AwaitTask t
#endif

    /// Catch an exception while binding m.
    /// NOTE: the semantics between a Sync.Catch and an Async.Catch are remarkably different. Most notably, Sync.Catch
    /// is just the application of Choice1Of2 to m since there is no evaluation taking place inside of it.
    static member inline Catch m =
#if SYNC
        Sync.Catch m
#else
        Async.Catch m
#endif

    static member inline Parallel s =
#if SYNC
        Sync.Parallel s
#else
        Async.Parallel s
#endif

[<AutoOpen; CompilationRepresentation (CompilationRepresentationFlags.ModuleSuffix)>]
module Vsync =

    /// The Vsync builder instance.
    /// Used like: vsync { return 0 }
    let vsync = Vsync ()

/// The Vsync alias.
type Vsync<'a> =
#if SYNC
    'a
#else
    Async<'a>
#endif

forth 将序列拆分为组

将序列拆分为组

gistfile1.fs
// code from https://stackoverflow.com/questions/6736464/split-seq-in-f/6737659#6737659
let splitBy f input =
  let i = ref 0
  input
  |> Seq.groupBy (fun x ->
    if f x then incr i
    !i)
  |> Seq.map snd

forth sqlProviderDemo.fs

sqlProviderDemo.fs
#I "../packages/SQLProvider.0.0.9-alpha/lib/net40"

#r "System.Data.dll"
#r "FSharp.Data.TypeProviders.dll"
#r "System.Data.Linq.dll"

open System.Data
open System.Data.Linq
open Microsoft.FSharp.Data.TypeProviders

type db = SqlDataConnection<"Data Source=localhost\SQLEXPRESS;Initial Catalog=northwind;Integrated Security=SSPI;">

let context = db.GetDataContext()

let q = query { for c in context.Customers do
                select c.CustomerID }

let q2 = query { for c in context.Categories do
                  select c.Picture }

context.CustOrderHist "ALFKI"

forth installDependencies.fs

installDependencies.fs
open System
open System.IO

Environment.CurrentDirectory <- __SOURCE_DIRECTORY__

if not (File.Exists "paket.exe") then
    let url = "https://github.com/fsprojects/Paket/releases/download/0.27.2/paket.exe"
    use wc = new Net.WebClient()
    let tmp = Path.GetTempFileName()
    wc.DownloadFile(url, tmp)
    File.Move(tmp,Path.GetFileName url);;

// Step 1. Resolve and install the packages 

#r "paket.exe"

Paket.Dependencies.Install """
    source https://nuget.org/api/v2
    nuget Suave
    nuget FSharp.Data 
    nuget FSharp.Charting
""";;


#r "packages/Suave/lib/net40/Suave.dll"
#r "packages/FSharp.Data/lib/net40/FSharp.Data.dll"
#r "packages/FSharp.Charting/lib/net40/FSharp.Charting.dll"

forth Sql Provider

Sql Provider

sqlProvider.fs
#I "../packages/SQLProvider.0.0.9-alpha/lib/net40"
#r "FSharp.Data.SqlProvider.dll"

open FSharp.Data.Sql

type sql = SqlDataProvider<ConnectionString = @"Server=JONWOOD4DDE\SQLEXPRESS;Database=northwind;Trusted_Connection=True",
                           DatabaseVendor = Common.DatabaseProviderTypes.MSSQLSERVER,
                           UseOptionTypes = true>

let context = sql.GetDataContext()

context.``[dbo].[Categories]``.Individuals.``As CategoryName``.``1, Beverages``.Table

forth gistfile1.fs

gistfile1.fs
//==========================================
// Working fully self-contained getting-started example for Suave Web Server scripting 
//
// Note you don't need to have _anything_ installed before starting with this script. Nothing
// but F# Interactive and this script.
//
// This script fetches the Paket.exe component which is referenced later in the script. 
// Initially the #r "paket.exe" reference is shown as unresolved. Once it has been
// downloaded by the user (by executing the first part of the script) the reference 
// shows as resolved and can be used.
//
// Paket is then used to fetch a set of F# packages, which are then used later inn the script.
// 

//------------------------------------------
// Step 0. Boilerplate to get the paket.exe tool

open System
open System.IO

Environment.CurrentDirectory <- __SOURCE_DIRECTORY__

if not (File.Exists "paket.exe") then
    let url = "https://github.com/fsprojects/Paket/releases/download/0.26.3/paket.exe"
    use wc = new Net.WebClient() in let tmp = Path.GetTempFileName() in wc.DownloadFile(url, tmp); File.Move(tmp,Path.GetFileName url)

// Step 1. Resolve and install the packages 

#r "paket.exe"

Paket.Dependencies.Install """
    source https://nuget.org/api/v2
    nuget Suave 0.16.0
    nuget FSharp.Data 
    nuget FSharp.Charting
""";;

// Step 2. Use the packages 

#r "packages/Suave/lib/Suave.dll"
#r "packages/FSharp.Data/lib/net40/FSharp.Data.dll"
#r "packages/FSharp.Charting/lib/net40/FSharp.Charting.dll"

let ctxt = FSharp.Data.WorldBankData.GetDataContext()

let data = ctxt.Countries.Algeria.Indicators.``GDP (current US$)``

open Suave                 // always open suave
open Suave.Http.Successful // for OK-result
open Suave.Web             // for config

web_server default_config (OK (sprintf "Hello World! In 2010 Algeria earned %f " data.[2010]))