Skip to content
William Blum edited this page Aug 16, 2019 · 4 revisions

Welcome to the FSharpLu wiki!

Documentation

This modules provides improved Json serialization over the default formatting used by Newtonsoft's Json.Net. The generated Json is more compact and maps more closely to the corresponding value definition in F#. For example the value [Some 5; None; Some 6] gets serialized to just

val it : string = "[ 5, null, 6 ]"

instead of the rather verbose

(* Default Json.Net serialization *)
val it : string = "[
    {
        "Case": "Some",
        "Fields": [ 5 ]
    },
    null,
    {
        "Case": "Some",
        "Fields": [ 6 ]
    }
]"

If you are doing web development with Giraffe you can also set FSharpLu.Json as the default serializer.

For more details see documentation for module FSharpLu.Json.

FSharpLu.TraceLogging

This modules offers F#-like strongly-typed logging helpers for the System.Diagnostics logging functions. For instance instead of calling System.Diagnostics.TraceInformation and providing untyped formatting parameters ala C# you can write instead:

Trace.info "Command '%s' with arguments %A exited with code: %d" command arguments exitCode

Another useful helper is Trace.failwith which behaves like F#'s failwith operator except that it also trace the error message using System.Diagnostics.TraceError before throwin an exception. Example:

if succeeds then
   someResult
else
   Trace.failwith "Something went wrong. Error message: %s" errorMessage
   

FSharpLu.Logger

This module provides a general purpose strongly-typed logging class for use in situations where global trace logging is not desirable. This can be used for instance in a multi-agent/multi-threaded setting where each agent needs to log information to a separate output channel without interfering with each other and without requiring synchronizing access to a global logger entity. It lets you instantiate logging objects of type Logger<'a,'s> where 'a is the type of messages being logged and 's is the type of the internal state maintained by the logger. You only need to provide a custom Action to be performed when a message is being logged and the Logger types provides all the strongly-typed logging helpers for you.

FSharpLu.StateMachine and FSharpLu.ServiceRequest

These modules implements a state-machine framework that you can use to implement reliable long-running asynchronous operations. The ServiceRequest module exposes queue-based request processing functions. The StateMachine module exposes an API to easily implement request handlers using state machines. The service requests manager persists the state of the state machine on some underlying queue system. This guarantees that requests gets picked up even if the agents processing the request die or get killed (e.g. VM failure, system update). Two queueing API implementations are provided: one in-memory (based on concurrent dictionary) and one based on Azure Storage queue API.

Here is an example demonstrating a service offering a single request Calculate implemented as an state-machine agent with four states. This examples demonstrate how agents can recursively call each other. In addition to the 'Goto' and 'Call' transitions used in the following example, other more complex types of transition are supported, like fork, joining on WhenAll and WhenAny condition, CoReturn, in-process and out-of-process asynchronous Sleep. See unit tests HofstadterCallTest.fs, StateMachineAgentTests.fs, QueueSchedulerTests.fs and AzureQueueSchedulerTests.fs for more examples.

/// Hofstadter Female and Male sequences test
/// See https://en.wikipedia.org/wiki/Hofstadter_sequence#Hofstadter_Female_and_Male_sequences
open Microsoft.FSharpLu.Actor.StateMachine
open Microsoft.FSharpLu.Actor.StateMachine.Agent
open Microsoft.FSharpLu.Actor.QueueScheduler
open Microsoft.FSharpLu.Actor.ServiceRequests
open Microsoft.FSharpLu.Actor
open System.Collections.Generic

type States =
    | Start
    | FirstCallReturn
    | SecondCallReturn
    | ReturnResult of int

type Gender = Male | Female
 with
 member x.Opposite =
    match x with
    | Male -> Female
    | Female -> Male 

type Message  =
| Calculate of StatefulRequest<Gender * int, States>

/// Transition function for a state machine agent calculating the
/// Hofstadter Female and Male sequences
let transition gender =
 run (sprintf "%A" gender) []
    Message.Calculate
    (fun (operations:Operations<_, _, _>) (gender:Gender, n:int) ->
        function
        | States.Start -> async {
            return 
                match n with
                | 0 when gender = Gender.Female ->
                    Transition.Goto (States.ReturnResult 1)
                | 0 when gender = Gender.Male ->
                    Transition.Goto (States.ReturnResult 0)
                | n ->
                    Transition.Call
                        ((fun m -> {
                            metadata = Some m
                            header = ()
                            calleeReturnResult = None
                            request = Calculate { state = States.Start; input = gender, n-1 } }),
                            States.FirstCallReturn)
           }

        | States.FirstCallReturn -> async {
            return Transition.Call
                    ((fun m ->
                        { 
                            metadata = Some m
                            header = ()
                            calleeReturnResult = None
                            request = Calculate { state = States.Start;  input = gender.Opposite, operations.ReturnResult<int>() }
                        }),
                    States.SecondCallReturn)
          }

        | States.SecondCallReturn -> async {
            let r = n - operations.ReturnResult<int>()
            return Transition.Goto <| ReturnResult r
          }

        | States.ReturnResult result -> async {
            return Transition.Return result
          })

FSharpLu.Option

Provides a set of common option type manipulation functions, including the Maybe monad.

FSharpLu.Configuration

Provides access to application (app.config) and website (web.config) configuration file.

let MySetting = Microsoft.FSharpLu.Configuration.getConfigValue "MySettingName"

FSharpLu.Diagnostics

Helpers for System.Diagnostics. For instance the startProcessAsync function allow you to start a system process within an async block and asynchronoulsy wait for it to terminate:

open Microsoft.FSharpLu.Diagnostics
async {
    let! exitCode = Process.startProcessAsync
                        command
                        arguments
                        workingDirectory
                        Process.ProcessStartFlags.None
                        Process.ProcessTimeoutAction.NoTimeout
    return exitCode = 0
}

FSharpLu.Async and FSharpLu.Async.Synchronization

Defines combinators and operators to work with asynchronous workflows. The Compete operator for instance allows you to start multiple asynchronous operations simultaneously and return as soon as one of them completes:

  let waitForNetworkOrCache = 
    Async.Compete 
        [
            async {
                let! networkResponse = AsyncReadFromNetwork()
                return networkResponse
            }
            async {
                let! cache = AsyncReadFromCache()
                return cache
            }
        ]   

The Synchronization sub-module implements classic thread synchronization objects like critical section, semaphore and events for use use with asynchronous computation.

open Microsoft.FSharpLu.Async
open Microsoft.FSharpLu.Async.Synchronization

let myTokenPool = new Async.Pool(10)
async {
    Trace.info "Acquiring token from the pool without timeout..."
    let! token = myTokenPool.AcquireAsync None
    Trace.info "Token acquired."
    return token
}

FSharpLu.File

File manipulation utilities.

FSharpLu.Parsing

Text parsing utilities.

FSharpLu.Security

Security related utilities.

FSharpLu.Text

String manipulation functions.

FSharpLu.ErrorHandling

Active patterns used to handle .Net aggregated exceptions in F#.

FSharpLu.Collection

Augments Seq module with additional sequence operators; provide F# helpers to operat on the IDictionary type.

Clone this wiki locally