Simplee.IO 1.0.5

There is a newer version of this package available.
See the version list below for details.
dotnet add package Simplee.IO --version 1.0.5                
NuGet\Install-Package Simplee.IO -Version 1.0.5                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Simplee.IO" Version="1.0.5" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Simplee.IO --version 1.0.5                
#r "nuget: Simplee.IO, 1.0.5"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Simplee.IO as a Cake Addin
#addin nuget:?package=Simplee.IO&version=1.0.5

// Install Simplee.IO as a Cake Tool
#tool nuget:?package=Simplee.IO&version=1.0.5                

Koio |> Simple.IO

Library Simplee.IO v1.0.5 implements common IO functionality used by all other Simple projects. The namespace of the library is Simplee.IO.

    open Simplee.IO

Here is the main functionality exposed:

  1. Stack free monad
  2. Queue free monad
  3. Reader monad
  4. State monad

1. Stack

1.1 The Free Monad

The library exposes a free monad for stack operations. The stack monad comes with 3 instructions:

  1. push instruction which pushes a value on top of the stack
  2. pop instruction which extracts the value from the top of the stack
  3. peek instruction which returns the value from the top of the stack without removing it from the stack.

The instructions use the error type provided in Simplee.Common package in order to return the evantual failures.

1.2 Computation Builder

This monad is wrapped within stk, a computation expression builder.

The user can construct flows into an imperative way using this builder.

    let flow = stk {
        let! _ = stkpush 10
        let! _ = stkpeek ()
        let! r = stkpop ()
        return r
        }
1.3 Built-in Interpreters

The flows generated with the builder can be interpreted using built-in interpretors. The library provides two interpretors:

  1. stklstr - an interpretor that transfors a flow of instructions into a listing.
  2. stkim - an interpretor that implements an in-memory stack which can have or not an upper limit.

Here is an example for the stack lister:

    flow
    |> stklst (fun () -> 10)
    |> List.iter (lstrln2str >> printfn "%s")

And here is an example for the in-memory stack:

    flow
    |> stkimrun (stkimE 10)        // start with an empty stack with upper limit set to 10
    |> fst
    |> printfn "Stack: %O"

There are several convenience function which can create an in-memory stack: stkimEU, stkimE, stkimA where you can set the upper limit of the stack and/or the initial values in the stack.

1.4 User-Defined Interpreters

A user can implement its own interpreter (eg. the stack is implemented on a database). The user will have to implement push, pop, peek, and pur functions, which stand for each of the stack instructions and for the function that return the final result of the workflow.

One of the arguments for these functions is the state instance which can be used to pass and or reuse information from one instruction to the next one. For example this state is the in-memory list of values for the in-memory interpreter. In the case of the lister, the state is the current line in the listing and the collection of listing lines accumulated so far.

Here is an example of the implementation for the push function:

    let private push (SLister (ln, _, _) as s) v =

        (ln, "psh", v |> sprintf "%A")
        |> SLstrLn
        |> lstappnd s,

        () |> Ok

2. Queue

2.1 The Free Monad

The library exposes a free monad for queue operations. The queue monad comes with 3 instructions:

  1. enqueue instruction which enqueues a value at the end of the queue.
  2. dequeue instruction which extracts the value from the begining of the queue.
  3. peek instruction which returns the value from the begining of the queue without remove it from the queue.

The instructions use the error type provided in Simplee.Common package in order to return the evantual failures.

1.2 Computation Builder

This monad is wrapped within queue, a computation expression builder.

The user can construct flows into an imperative way using this builder.

    let flow = queue {
        let! _ = queenq 10
        let! _ = quepeek ()
        let! r = quedeq ()
        return r
        }

3. Reader Monad

The library exposes a Reader monad, which is a function that reads from a given environment and returns a value.

type Reader<'e, 'a> = Reader of ('e -> 'a)

The main functions related to the Reader monad are rdrrun which executes a reader and/or a reader flow, rdrbind which binds a reader to a function, rdr which is the computation expression builder.

You can use the reader in a functional way:

    let readRun         = Reader (fun _ -> true)
    let readCfgLocal    = Reader (fun _ -> "local configuration")
    let readCfgRemote   = Reader (fun _ -> "remote configuration")

    let readCfg = function
        | true  -> readCfgLocal 
        | _     -> readCfgRemote

    let flow = rdrbind readRun readCfg
    let res = () |> rdrrun flow

    Assert.Equal("local configuration", res)

You can use the built-in computation expression builder as well, for imperative programming:

    let readRun         = Reader (fun _ -> false)
    let readCfgLocal    = Reader (fun _ -> "local configuration")
    let readCfgRemote   = Reader (fun _ -> "remote configuration")

    let flow = reader {
        let! b = readRun

        match b with
        | true -> return! readCfgLocal
        | _    -> return! readCfgRemote
    }

    let res = () |> rdrrun flow
    Assert.Equal("remote configuration", res)

3. State Monad

The library exposes a State monad, which is a function that transition from a given state to another state while generating also a value at the end of the transition.

type State<'a, 's> = State of ('s -> 'a * 's)

The main functions related to the State monad are sttrun which executes a state transition and/or a state flow, sttbind which binds a state to a function, state which is the computation expression builder.

You can use the state in a functional way:

    let t0 = State (fun n -> (n,   n+1))
    let t1 = State (fun n -> (n+1, n+1))

    let fn n = 
        match n % 2 with
        | 0 -> t0
        | _ -> t1

    let flow = sttbind t0 fn
    let res = 1 |> sttrun flow |> fst

    // We run t0 from 1 to 2, the returned value should be 1 + 0
    // Since 1 % 2 is 1 
    // We run t1 from 2 to 3, the returned value should be 2 + 1

    Assert.Equal(3, res)

You can use the built-in computation expression builder as well, for imperative programming:

    let t0 = State (fun n -> (n,   n+1))
    let t1 = State (fun n -> (n+1, n+1))

    let flow = state {
        let! r = t0            
            
        match r % 2 with
        | 0 -> return! t0
        | _ -> return! t1
    }

    let res = 1 |> sttrun flow |> fst
    Assert.Equal(3, res)

A. Installation

You can install the Simplee.IO nuget package by using one of the following commands:

PM> Install-Package Simplee.IO -Version 1.0.5
> dotnet add package Simplee.IO --version 1.0.5
> paket add Simplee.IO --version 1.0.5
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 is compatible.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Added the state monad.