Defines the basic operations over a monad, a concept from a branch of mathematics known as category theory. From the perspective of an F# programmer, however, it is best to think of a monad as an abstract datatype of actions. F#+ generic computation expressions provide a convenient syntax for writing monadic expressions.
return x
/result x
(>>=) x f
static member Return (x: 'T) : 'Monad<'T>
static member (>>=) (x: Monad<'T>, f: 'T->Monad<'U>) : Monad<'U>
Note: return
can't be used outside computation expressions, use result
instead.
static member Join (x:'Monad<'Monad<'T>>) :'Monad<'T>
return a >>= k = k a
m >>= return = m
m >>= (fun x -> k x >>= h) = (m >>= k) >>= h
From F#
seq<'T>
list<'T>
array<'T>
option<'T>
Lazy<'T>
Async<'T>
Result<'T,'U>
Choice<'T,'U>
'Monoid * 'T
Task<'T>
'R->'T
ResizeArray<'T>
From F#+
Identity<'T>
Cont<'R,'T>
ContT<'R,'T>
Reader<'R,'T>
ReaderT<'R,'Monad<'T>>
Writer<'Monoid,'T>
WriterT<'Monad<'T * 'Monoid>>
State<'S,'T * 'S>
StateT<'S,'Monad<'T * 'S>>
OptionT<'Monad<option<'T>>
SeqT<'Monad<seq<'T>>
ListT<'Monad<list<'T>>
ResultT<'Monad<Result<'T,'TError>>
ChoiceT<'Monad<Choice<'T,'TError>>
Free<'Functor<'T>,'T>
NonEmptyList<'T>
-
DList<'T>
Suggest another concrete implementation
#r @"../../src/FSharpPlus/bin/Release/net45/FSharpPlus.dll"
open FSharpPlus
open FSharpPlus.Data
// Monads allow us to use our generic computation expressions
// This will return the list [11;21;12;22] which is both lists combined in different ways with the (+) operation
let lst11n21n12n22 =
monad {
let! x1 = [1; 2]
let! x2 = [10; 20]
return ((+) x1 x2) }
// This is the same example but with a non-empty list
let neLst11n21n12n22 =
monad {
let! x1 = { NonEmptyList.Head = 1; Tail = [2] }
let! x2 = { NonEmptyList.Head = 10; Tail = [20] }
return ((+) x1 x2)}
// And now an example with options
let some14 =
monad {
let! x1 = Some 4
let! x2 = tryParse "10"
return ((+) x1 x2) }
// MONAD TRANSFORMERS
// ==================
//
// Monads do not compose directly, we need to use Monad Transformers
let fn : ResultT<Reader<int,Result<_,string>>> =
monad {
let! x1 = lift ask
let! x2 =
if x1 > 0 then result 1
else ResultT (result (Error "Negative value"))
return x1 + x2
}
let x = (fn |> ResultT.run |> Reader.run) 10
// Result<int,string> = Ok 11
let y = (fn |> ResultT.run |> Reader.run) -1
// Result<int,string> = Error "Negative value"
|
// The following example comes from Haskell
// async is used instead of IO
open System
// First let's define some functions we'll use later
let getLine = async { return Console.ReadLine () }
let putStrLn x = async { printfn "%s" x }
let isValid s =
String.length s >= 8
&& String.exists Char.IsLetter s
&& String.exists Char.IsNumber s
&& String.exists Char.IsPunctuation s
let decodeError = function
| -1 -> "Password not valid"
| _ -> "Unknown"
// Now the following functions compose the Error monad with the Async one.
let getValidPassword : ResultT<_> =
monad {
let! s = liftAsync getLine
if isValid s then return s
else return! throw -1}
</catch/>
(fun s -> throw ("The error was: " + decodeError s))
let askPassword = monad {
do! lift <| putStrLn "Insert your new password:"
let! value = getValidPassword
//do! lift <| putStrLn "Storing in database..."
return value}
//try -> Async.RunSynchronously (ResultT.run askPassword)
// After getting used to monadic CEs it's natural
// to feel the need to combine monads
// (from https://stackoverflow.com/a/37900264 )
module CombineWriterWithResult =
let divide5By = function
| 0.0 -> Error "Divide by zero"
| x -> Ok (5.0 / x)
let eitherConv logSuccessF logFailF f v =
ResultT <|
match f v with
| Ok a -> Writer(Ok a, ["Success: " + logSuccessF a])
| Error b -> Writer(Error b, ["ERROR: " + logFailF b])
let ew = monad {
let! x = eitherConv (sprintf "%f") (sprintf "%s") divide5By 6.0
let! y = eitherConv (sprintf "%f") (sprintf "%s") divide5By 3.0
let! z = eitherConv (sprintf "%f") (sprintf "%s") divide5By 0.0
return (x, y, z) }
let (_, log) = ew |> ResultT.run |> Writer.run
// You can also stack monad transformers.
// A monad transformer and a monad is itself a monad, so you can pass that into another monad transformer.
// For example, below we are stacking them like:
// type Example = ReaderT<DateTime, ResultT<Writer<string list, Result<string * string * string, string>>>>)
// Catch and throw is generic over all monad transformers in F#+ so catch works in this example
// because there is a Result in the stack. We use it here to consolidate Result's 'TError.
module CombineReaderWithWriterWithResult =
let divide5By : float -> Result<float, string> = function
| 0.0 -> Error "Divide by zero"
| x -> Ok (5.0 / x)
let otherDivide5By : float -> Result<float, unit> = function
| 0.0 -> Error ()
| x -> Ok (5.0 / x)
let eitherConv f v =
ReaderT <| fun (now : System.DateTime) ->
ResultT <|
match f v with
| Ok a -> Writer(Ok a, [sprintf "Success at %s: %A" (now.ToString "o") a])
| Error b -> Writer(Error b, [sprintf "ERROR at %s: %A" (now.ToString "o") b])
let divide = monad {
let! w = eitherConv divide5By 6.0
let! x = eitherConv divide5By 3.0
let! y = eitherConv divide5By 0.0
let! z = eitherConv otherDivide5By 0.0 </catch/> (throw << (fun _ -> "Unknown error"))
return (w, x, y, z) }
let run expr = ReaderT.run expr >> ResultT.run >> Writer.run
let (_, log) = run divide DateTime.UtcNow
// Many popular F# libraries are in fact an instantiation of a specific monad combination.
// The following example demonstrate how to code a mini-Suave lib in a few lines
module Suave =
// setup something that reminds us of what Suave can work with
// this is an overly simplified model of Suave in order to show how OptionT can be used
// in conjunction with generic Kleisli composition (fish) operator
type WebPart<'a> = 'a -> OptionT<Async<'a option>>
let inline succeed x = async.Return (Some x)
module WebPart =
/// Comment from <a href="https://github.com/SuaveIO/suave/blob/v2.4.3/src/Suave/WebPart.fsi#L39-L42">WebPart.fsi</a>
/// Entry-point for composing the applicative routes of the http application,
/// by iterating the options, applying the context, arg, to the predicate
/// from the list of options, until there's a match/a Some(x) which can be
/// run.
let choose (options: WebPart<'a> list) = fun x -> choice (List.map ((|>) x) options)
module Http =
type HttpResponse = { status: int; content: string }
type HttpRequest = { url: Uri; ``method``: string }
type HttpContext = { request: HttpRequest; response: HttpResponse }
module Successful =
open Http
let private withStatusCode statusCode s =
OptionT << fun ctx -> { ctx with response = { ctx.response with status = statusCode; content = s }} |> succeed
let OK s = withStatusCode 200 s
let BAD_REQUEST s = withStatusCode 400 s
module Filters =
open Http
let ``method`` (m: string) =
OptionT << fun (x: HttpContext) -> async.Return (if (m = x.request.``method``) then Some x else None)
let GET (x : HttpContext) = ``method`` "GET" x
let POST (x : HttpContext) = ``method`` "POST" x
let path s =
OptionT << fun (x: HttpContext) -> async.Return (if (s = x.request.url.AbsolutePath) then Some x else None)
// Stub implementations: here you can plug Fleece or another similar Json library
let toJson o : string = failwith "Not implemented"
let ofJson (s: string) = failwith "Not implemented"
module Request =
let tryGet _s (_r: Http.HttpRequest) = Ok "FORM VALUE"
let authenticated (f: Http.HttpContext -> int -> OptionT<Async<'a option>>) =
// we assume that authenticated executes f only if auth, otherwise returns 401
// we fake it as:
fun (ctx: Http.HttpContext) -> f ctx -1
// Usage:
open Successful
open Filters
type Note = { id: int; text: string }
type NoteList = { notes: Note list; offset: int; chunk: int; total: int }
type IDb =
abstract member getUserNotes: int -> Async<NoteList>
abstract member addUserNote: int -> string -> Async<Note>
type OverviewViewModel = { myNotes: Note list }
let app (db: IDb) =
let overview =
GET >=> (authenticated <| fun ctx userId ->
monad {
let! res = lift (db.getUserNotes userId)
let ovm = toJson { myNotes = res.notes }
return! OK ovm ctx
})
let register =
POST >=> (authenticated <| fun ctx userId ->
monad {
match ctx.request |> Request.tryGet "text" with
| Ok text ->
let! newNote = lift (db.addUserNote userId text)
let rvm = toJson newNote
return! OK rvm ctx
| Error msg ->
return! BAD_REQUEST msg ctx
})
WebPart.choose [ path "/" >=> (OK "/")
path "/note" >=> register
path "/notes" >=> overview ]
namespace FSharpPlus
namespace FSharpPlus.Data
val lst11n21n12n22 : int list
val monad<'monad<'t>> : MonadFxBuilder<'monad<'t>>
val x1 : int
val x2 : int
val neLst11n21n12n22 : NonEmptyList<int>
Multiple items
module NonEmptyList
from FSharpPlus.Data
--------------------
type NonEmptyList<'t> =
{ Head: 't
Tail: 't list }
interface NonEmptySeq<'t>
interface IReadOnlyList<'t>
interface IReadOnlyCollection<'t>
interface IEnumerable
interface IEnumerable<'t>
member GetSlice : (int option * int option -> NonEmptyList<'t>)
member Item : (int -> 't)
member Length : int
static member Choice : source:NonEmptyList<'Alt<'T>> -> 'Alt<'T> (requires member IsAltLeftZero and member ( <|> ))
static member Duplicate : s:NonEmptyList<'a> * _impl:Duplicate -> NonEmptyList<NonEmptyList<'a>>
...
val some14 : int option
union case Option.Some: Value: 'T -> Option<'T>
val tryParse : value:string -> 'b option (requires member TryParse)
namespace System
val getLine : Async<string>
val async : AsyncBuilder
type Console =
static member BackgroundColor : ConsoleColor with get, set
static member Beep : unit -> unit + 1 overload
static member BufferHeight : int with get, set
static member BufferWidth : int with get, set
static member CapsLock : bool
static member Clear : unit -> unit
static member CursorLeft : int with get, set
static member CursorSize : int with get, set
static member CursorTop : int with get, set
static member CursorVisible : bool with get, set
...
Console.ReadLine() : string
val putStrLn : x:string -> Async<unit>
val x : string
val printfn : format:Printf.TextWriterFormat<'T> -> 'T
val isValid : s:string -> bool
val s : string
Multiple items
type String =
new : value:char[] -> string + 8 overloads
member Chars : int -> char
member Clone : unit -> obj
member CompareTo : value:obj -> int + 1 overload
member Contains : value:string -> bool + 3 overloads
member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
member EndsWith : value:string -> bool + 3 overloads
member EnumerateRunes : unit -> StringRuneEnumerator
member Equals : obj:obj -> bool + 2 overloads
member GetEnumerator : unit -> CharEnumerator
...
--------------------
String(value: char []) : String
String(value: nativeptr<char>) : String
String(value: nativeptr<sbyte>) : String
String(value: ReadOnlySpan<char>) : String
String(c: char, count: int) : String
String(value: char [], startIndex: int, length: int) : String
String(value: nativeptr<char>, startIndex: int, length: int) : String
String(value: nativeptr<sbyte>, startIndex: int, length: int) : String
String(value: nativeptr<sbyte>, startIndex: int, length: int, enc: Text.Encoding) : String
val length : str:string -> int
val exists : predicate:(char -> bool) -> str:string -> bool
type Char =
struct
member CompareTo : value:obj -> int + 1 overload
member Equals : obj:obj -> bool + 1 overload
member GetHashCode : unit -> int
member GetTypeCode : unit -> TypeCode
member ToString : unit -> string + 1 overload
static val MaxValue : char
static val MinValue : char
static member ConvertFromUtf32 : utf32:int -> string
static member ConvertToUtf32 : highSurrogate:char * lowSurrogate:char -> int + 1 overload
static member GetNumericValue : c:char -> float + 1 overload
...
end
Char.IsLetter(c: char) : bool
Char.IsLetter(s: string, index: int) : bool
Char.IsNumber(c: char) : bool
Char.IsNumber(s: string, index: int) : bool
Char.IsPunctuation(c: char) : bool
Char.IsPunctuation(s: string, index: int) : bool
val decodeError : _arg1:int -> string
val getValidPassword : ResultT<Async<Result<string,string>>>
Multiple items
union case ResultT.ResultT: 'monad<'result<'t,'e>> -> ResultT<'monad<'result<'t,'e>>>
--------------------
module ResultT
from FSharpPlus.Data
--------------------
[<Struct>]
type ResultT<'monad<'result<'t,'e>>> =
| ResultT of 'monad<'result<'t,'e>>
static member CallCC : f:(('T -> ResultT<'MonadCont<'R,Result<'U,'E>>>) -> ResultT<'MonadCont<'R, Result<'T,'E>>>) -> ResultT<'MonadCont<'R, Result<'T,'E>>> (requires member CallCC)
static member Catch : ResultT<'MonadError<'E1,'T>> * f:('E1 -> ResultT<'Monad<Result<'T,'E2>>>) -> ResultT<'Monad<Result<'T,'E2>>> (requires member ( >>= ) and member Return)
static member Delay : body:(unit -> ResultT<'Monad<'Result<'T,'E>>>) -> ResultT<'a2> (requires member Delay)
static member LiftAsync : x:Async<'T> -> ResultT<'MonadAsync<'T>> (requires member Return and member ( >>= ) and member Map and member LiftAsync)
static member Listen : m:ResultT<'a1> -> ResultT<'MonadWriter<'Monoid,Result<'T*'Monoid,'E>>> (requires member ( >>= ) and member Return and member Listen)
static member Local : ResultT<'MonadReader<'R2,Result<'R2,'E>>> * f:('R1 -> 'R2) -> ResultT<'a4> (requires member Local)
static member Pass : m:ResultT<'a1> -> ResultT<'MonadWriter<'Monoid,Result<'T,'E>>> (requires member ( >>= ) and member Map and member Return and member Pass and member Return)
static member Put : x:'S -> ResultT<'MonadState<'S,Result<_,'E>>> (requires member Return and member ( >>= ) and member Map and member Put)
static member Return : x:'T -> ResultT<'Monad<'Result<'T,'E>>> (requires member Return)
static member Tell : w:'Monoid -> ResultT<'Writer<'Monoid,Result<unit,'E>>> (requires member Return and member ( >>= ) and member Map and member Tell)
...
val liftAsync : x:Async<'T> -> 'MonadAsync<'T> (requires member LiftAsync)
val throw : error:'E -> ''MonadError<'E,'T> (requires member Throw)
val catch : value:''MonadError<'E1,'T> -> handler:('E1 -> ''MonadError<'E2,'T>) -> ''MonadError<'E2,'T> (requires member Catch)
val s : int
val askPassword : ResultT<Async<Result<string,string>>>
val lift : x:'Monad<'T> -> 'MonadTrans<'Monad<'T>> (requires member Lift)
val value : string
val divide5By : _arg1:float -> Result<float,string>
union case Result.Error: ErrorValue: 'TError -> Result<'T,'TError>
val x : float
union case Result.Ok: ResultValue: 'T -> Result<'T,'TError>
val eitherConv : logSuccessF:('a -> string) -> logFailF:('b -> string) -> f:('c -> Result<'a,'b>) -> v:'c -> ResultT<Writer<string list,Result<'a,'b>>>
val logSuccessF : ('a -> string)
val logFailF : ('b -> string)
val f : ('c -> Result<'a,'b>)
val v : 'c
val a : 'a
Multiple items
union case Writer.Writer: ('t * 'monoid) -> Writer<'monoid,'t>
--------------------
module Writer
from FSharpPlus.Data
--------------------
[<Struct>]
type Writer<'monoid,'t> =
| Writer of ('t * 'monoid)
static member Extract : Writer<'T,'W> -> 'T
static member Listen : m:Writer<'Monoid,'T> -> Writer<'Monoid,('T * 'Monoid)>
static member Pass : m:Writer<'Monoid,('T * ('Monoid -> 'Monoid))> -> Writer<'Monoid,'T>
static member Return : x:'T -> Writer<'Monoid,'T> (requires member Zero)
static member Tell : w:'Monoid -> Writer<'Monoid,unit>
static member ( =>> ) : g:Writer<'T,'W> * f:(Writer<'T,'W> -> 'U) -> Writer<'U,'W>
static member ( >>= ) : x:Writer<'Monoid,'T> * f:('T -> Writer<'Monoid,'U>) -> Writer<'Monoid,'U> (requires member ( + ))
static member ( <*> ) : f:Writer<'Monoid,('T -> 'U)> * x:Writer<'Monoid,'T> -> Writer<'Monoid,'U> (requires member ( + ))
val b : 'b
val ew : ResultT<Writer<string list,Result<(float * float * float),string>>>
val sprintf : format:Printf.StringFormat<'T> -> 'T
val y : float
val z : float
val log : string list
val run : ResultT<'Monad<'Result<'T,'E>>> -> 'Monad<'Result<'T,'E>>
val run : Writer<'Monoid,'T> -> 'T * 'Monoid
Multiple items
val float : value:'T -> float (requires member op_Explicit)
--------------------
type float = Double
--------------------
type float<'Measure> = float
Multiple items
module Result
from FSharpPlus.Data
--------------------
module Result
from FSharpPlus
--------------------
module Result
from Microsoft.FSharp.Core
--------------------
[<Struct>]
type Result<'T,'TError> =
| Ok of ResultValue: 'T
| Error of ErrorValue: 'TError
Multiple items
val string : value:'T -> string
--------------------
type string = String
val otherDivide5By : _arg1:float -> Result<float,unit>
type unit = Unit
val eitherConv : f:('a -> Result<'b,'c>) -> v:'a -> ReaderT<DateTime,ResultT<Writer<string list,Result<'b,'c>>>>
val f : ('a -> Result<'b,'c>)
val v : 'a
Multiple items
union case ReaderT.ReaderT: ('r -> 'monad<'t>) -> ReaderT<'r,'monad<'t>>
--------------------
module ReaderT
from FSharpPlus.Data
--------------------
[<Struct>]
type ReaderT<'r,'monad<'t>> =
| ReaderT of ('r -> 'monad<'t>)
static member CallCC : f:(('T -> ReaderT<'R,Cont<'a4,'U>>) -> ReaderT<'R,'MonadCont<'C,'T>>) -> ReaderT<'R,'MonadCont<'C,'T>> (requires member CallCC)
static member Catch : m:ReaderT<'R,'MonadError<'E1,'T>> * h:('E1 -> ReaderT<'R,'MonadError<'E2,'T>>) -> ReaderT<'R,'MonadError<'E2,'T>> (requires member Catch)
static member Delay : body:(unit -> ReaderT<'R,'Monad<'T>>) -> ReaderT<'R,'a4> (requires member Delay)
static member LiftAsync : x:Async<'T> -> ReaderT<'R,'MonadAsync<'T>> (requires member LiftAsync)
static member Listen : ReaderT<'R,'a3> -> ReaderT<'R,'MonadWriter<'Monoid,'T*'Monoid>> (requires member Listen)
static member Local : ReaderT<'R2,'Monad<'T>> * f:('R1 -> 'R2) -> ReaderT<'R1,'Monad<'T>>
static member Pass : ReaderT<'R,'a3> -> ReaderT<'R,'MonadWriter<'Monoid,'T>> (requires member Pass)
static member Put : x:'a2 -> ReaderT<'R,'MonadState<'S, unit>> (requires member Put)
static member Return : x:'T -> ReaderT<'R,'Monad<'T>> (requires member Return)
static member Tell : w:'a2 -> ReaderT<'R,'MonadWriter<'Monoid,unit>> (requires member Tell)
...
val now : DateTime
Multiple items
type DateTime =
struct
new : ticks:int64 -> DateTime + 10 overloads
member Add : value:TimeSpan -> DateTime
member AddDays : value:float -> DateTime
member AddHours : value:float -> DateTime
member AddMilliseconds : value:float -> DateTime
member AddMinutes : value:float -> DateTime
member AddMonths : months:int -> DateTime
member AddSeconds : value:float -> DateTime
member AddTicks : value:int64 -> DateTime
member AddYears : value:int -> DateTime
...
end
--------------------
DateTime ()
(+0 other overloads)
DateTime(ticks: int64) : DateTime
(+0 other overloads)
DateTime(ticks: int64, kind: DateTimeKind) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int, calendar: Globalization.Calendar) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, kind: DateTimeKind) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, calendar: Globalization.Calendar) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int, kind: DateTimeKind) : DateTime
(+0 other overloads)
val a : 'b
val b : 'c
val divide : ReaderT<DateTime,ResultT<Writer<string list,Result<(float * float * float * float),string>>>>
val w : float
val run : expr:ReaderT<'a,ResultT<Writer<'b,'c>>> -> ('a -> 'c * 'b)
val expr : ReaderT<'a,ResultT<Writer<'b,'c>>>
val run : ReaderT<'R,'Monad<'T>> -> ('R -> 'Monad<'T>)
property DateTime.UtcNow: DateTime with get
module Suave
from Abstraction-monad
type WebPart<'a> = 'a -> OptionT<Async<'a option>>
Multiple items
union case OptionT.OptionT: 'monad<option<'t>> -> OptionT<'monad<option<'t>>>
--------------------
module OptionT
from FSharpPlus.Data
--------------------
[<Struct>]
type OptionT<'monad<option<'t>>> =
| OptionT of 'monad<option<'t>>
static member CallCC : f:(('T -> OptionT<'MonadCont<'R,option<'U>>>) -> OptionT<'MonadCont<'R,option<'T>>>) -> OptionT<'MonadCont<'R,option<'T>>> (requires member CallCC)
static member Catch : m:OptionT<'MonadError<'E1,'T>> * h:('E1 -> OptionT<'MonadError<'E2,'T>>) -> OptionT<'MonadError<'E2,'T>> (requires member Catch)
static member Delay : body:(unit -> OptionT<'Monad<option<'T>>>) -> OptionT<'Monad<option<'T>>> (requires member Delay)
static member LiftAsync : x:Async<'T> -> OptionT<'MonadAsync<'T>> (requires member Return and member ( >>= ) and member Map and member LiftAsync)
static member Listen : m:OptionT<'a1> -> OptionT<''MonadWriter<'Monoid, option<'T>>> (requires member ( >>= ) and member Return and member Listen)
static member Local : OptionT<'MonadReader<'R2,'T>> * f:('R1 -> 'R2) -> OptionT<'a4> (requires member Local)
static member Pass : m:OptionT<'a1> -> OptionT<'MonadWriter<'Monoid, option<'T>>> (requires member ( >>= ) and member Map and member Return and member Pass and member Return)
static member Put : x:'S -> OptionT<'MonadState<unit,'S>> (requires member Return and member ( >>= ) and member Map and member Put)
static member Return : x:'T -> OptionT<'Monad<option<'T>> (requires member Return)
static member Tell : w:'Monoid -> OptionT<'MonadWriter<'Monoid, unit>> (requires member Return and member ( >>= ) and member Map and member Tell)
...
Multiple items
module Async
from FSharpPlus
--------------------
type Async =
static member AsBeginEnd : computation:('Arg -> Async<'T>) -> ('Arg * AsyncCallback * obj -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit)
static member AwaitEvent : event:IEvent<'Del,'T> * ?cancelAction:(unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate)
static member AwaitIAsyncResult : iar:IAsyncResult * ?millisecondsTimeout:int -> Async<bool>
static member AwaitTask : task:Task -> Async<unit>
static member AwaitTask : task:Task<'T> -> Async<'T>
static member AwaitWaitHandle : waitHandle:WaitHandle * ?millisecondsTimeout:int -> Async<bool>
static member CancelDefaultToken : unit -> unit
static member Catch : computation:Async<'T> -> Async<Choice<'T,exn>>
static member Choice : computations:seq<Async<'T option>> -> Async<'T option>
static member FromBeginEnd : beginAction:(AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
...
--------------------
type Async<'T> =
Multiple items
val option : f:('g -> 'h) -> n:'h -> _arg1:'g option -> 'h
--------------------
type 'T option = Option<'T>
val succeed : x:'a -> Async<'a option>
val x : 'a
val choose : options:WebPart<'a> list -> x:'a -> OptionT<Async<'a option>>
Comment from <a href="https://github.com/SuaveIO/suave/blob/v2.4.3/src/Suave/WebPart.fsi#L39-L42">WebPart.fsi</a>
Entry-point for composing the applicative routes of the http application,
by iterating the options, applying the context, arg, to the predicate
from the list of options, until there's a match/a Some(x) which can be
run.
val options : WebPart<'a> list
type 'T list = List<'T>
val choice : x:'Foldable<'Alternative<'T>> -> 'Alternative<'T>> (requires member Choice)
Multiple items
module List
from FSharpPlus.Data
--------------------
module List
from FSharpPlus
--------------------
module List
from Microsoft.FSharp.Collections
--------------------
type List<'T> =
| ( [] )
| ( :: ) of Head: 'T * Tail: 'T list
interface IReadOnlyList<'T>
interface IReadOnlyCollection<'T>
interface IEnumerable
interface IEnumerable<'T>
member GetSlice : startIndex:int option * endIndex:int option -> 'T list
member Head : 'T
member IsEmpty : bool
member Item : index:int -> 'T with get
member Length : int
member Tail : 'T list
...
val map : mapping:('T -> 'U) -> list:'T list -> 'U list
type HttpResponse =
{ status: int
content: string }
HttpResponse.status: int
Multiple items
val int : value:'T -> int (requires member op_Explicit)
--------------------
type int = int32
--------------------
type int<'Measure> = int
HttpResponse.content: string
type HttpRequest =
{ url: Uri
method: string }
HttpRequest.url: Uri
Multiple items
type Uri =
new : uriString:string -> Uri + 5 overloads
member AbsolutePath : string
member AbsoluteUri : string
member Authority : string
member DnsSafeHost : string
member Equals : comparand:obj -> bool
member Fragment : string
member GetComponents : components:UriComponents * format:UriFormat -> string
member GetHashCode : unit -> int
member GetLeftPart : part:UriPartial -> string
...
--------------------
Uri(uriString: string) : Uri
Uri(uriString: string, uriKind: UriKind) : Uri
Uri(baseUri: Uri, relativeUri: string) : Uri
Uri(baseUri: Uri, relativeUri: Uri) : Uri
type HttpContext =
{ request: HttpRequest
response: HttpResponse }
HttpContext.request: HttpRequest
HttpContext.response: HttpResponse
module Http
from Abstraction-monad.Suave
val private withStatusCode : statusCode:int -> s:string -> (HttpContext -> OptionT<Async<HttpContext option>>)
val statusCode : int
val ctx : HttpContext
val OK : s:string -> (HttpContext -> OptionT<Async<HttpContext option>>)
val BAD_REQUEST : s:string -> (HttpContext -> OptionT<Async<HttpContext option>>)
val m : string
val x : HttpContext
union case Option.None: Option<'T>
val GET : x:HttpContext -> OptionT<Async<HttpContext option>>
val POST : x:HttpContext -> OptionT<Async<HttpContext option>>
val path : s:string -> (HttpContext -> OptionT<Async<HttpContext option>>)
val toJson : o:'a -> string
val o : 'a
val failwith : message:string -> 'T
val ofJson : s:string -> 'a
val tryGet : _s:'a -> _r:Http.HttpRequest -> Result<string,'b>
val _s : 'a
val _r : Http.HttpRequest
val authenticated : f:(Http.HttpContext -> int -> OptionT<Async<'a option>>) -> ctx:Http.HttpContext -> OptionT<Async<'a option>>
val f : (Http.HttpContext -> int -> OptionT<Async<'a option>>)
val ctx : Http.HttpContext
module Successful
from Abstraction-monad.Suave
module Filters
from Abstraction-monad.Suave
type Note =
{ id: int
text: string }
Note.id: int
Note.text: string
type NoteList =
{ notes: Note list
offset: int
chunk: int
total: int }
NoteList.notes: Note list
NoteList.offset: int
NoteList.chunk: int
NoteList.total: int
type IDb =
interface
abstract member addUserNote : int -> string -> Async<Note>
abstract member getUserNotes : int -> Async<NoteList>
end
type OverviewViewModel =
{ myNotes: Note list }
OverviewViewModel.myNotes: Note list
val app : db:IDb -> (Http.HttpContext -> OptionT<Async<Http.HttpContext option>>)
val db : IDb
val overview : (Http.HttpContext -> OptionT<Async<Http.HttpContext option>>)
val GET : x:Http.HttpContext -> OptionT<Async<Http.HttpContext option>>
val userId : int
val res : NoteList
val ovm : string
val OK : s:string -> (Http.HttpContext -> OptionT<Async<Http.HttpContext option>>)
val register : (Http.HttpContext -> OptionT<Async<Http.HttpContext option>>)
val POST : x:Http.HttpContext -> OptionT<Async<Http.HttpContext option>>
module Request
from Abstraction-monad.Suave
val text : string
val newNote : Note
val rvm : string
val msg : string
val BAD_REQUEST : s:string -> (Http.HttpContext -> OptionT<Async<Http.HttpContext option>>)
Multiple items
module WebPart
from Abstraction-monad.Suave
--------------------
type WebPart<'a> = 'a -> OptionT<Async<'a option>>
val path : s:string -> (Http.HttpContext -> OptionT<Async<Http.HttpContext option>>)