diff options
| author | 2021-10-09 21:45:43 -0400 | |
|---|---|---|
| committer | 2021-10-09 21:45:43 -0400 | |
| commit | 8c8496da46660f3d0e45171a3cc3d8d3159dfa2f (patch) | |
| tree | a5f37277cfa9b0a72b2d1632b20ae781716b6a5e /src/letsqlite.mli | |
move over stuff from old project
Diffstat (limited to '')
| -rw-r--r-- | src/letsqlite.mli | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/src/letsqlite.mli b/src/letsqlite.mli new file mode 100644 index 0000000..001b228 --- /dev/null +++ b/src/letsqlite.mli @@ -0,0 +1,141 @@ +(** {1 Type definitions} + +Types used for monad composition. +*) +type 'a stmt_m = +| Failed of Sqlite3.Rc.t +| Norm of ('a * Sqlite3.stmt) +(** The ['a] value in the [stmt_m] is referred to as the bundled value. + A function may "fail with [e]", in which it returns [Failed e], + or it may "return a value", in which it returns [Norm v s]. + They are collectively refered to as the monad's values. + + The bundled {Sqlite.stmt} value is refered to as [S], and the + value bundled is refered to as [V]. + + {i Never directly use [Failed].} You run the likelihood of leaking + memory. +*) + +type ('a,'b) monad_fun = ('a * Sqlite3.stmt) -> 'b stmt_m + +type rowdata = (string, Sqlite3.Data.t) Hashtbl.t + +(** {1 Primary Functions} *) + +val (>>$) : 'a stmt_m -> ('a,'b) monad_fun -> 'b stmt_m +(** [>>$] is the monadic composition function. + + [s >>$ f] return [s] if [s] is [Failed] and [f V S] otherwise. +*) + +val (let$) : 'a stmt_m -> ('a,'b) monad_fun -> 'b stmt_m +(** [let$ (v,s) = f (V,S) in ...] is equivalent to + [f (V,S) >>$ (fun (v,s) -> ...)]. *) + +val (>-$) : 'a stmt_m -> ('a,'b) monad_fun -> 'a stmt_m +(** [>-$] is the passthrough function. + + [s >-$ f] is equivalent to [s >>$ f] except that the bundled + value from [f (V,S)] is discarded and replaced with [V]. This function + passes the original [V] through. +*) + +(** {1 Non-Execution Functions} + +These functions do not execute any SQL queries. They exist to make dealing +with the monad easier. +*) + +val inject : 'a -> ('b,'a) monad_fun +(** [inject x] returns [Norm x S], discarding [V]. *) + +val fail : Sqlite3.Rc.t -> ('a,'b) monad_fun +(** [fail e] finalizes [S] and returns [Failure], where the error + code is [e] if [e] is not a success error code, and the return code + of {finalize} otherwise. +*) + +val stmtfail : Sqlite3.Rc.t -> Sqlite3.stmt -> unit stmt_m +(** [stmtfail e s] is equivalent to [fail] except it assembles a statement + with unit type. *) + +val lift_err : Sqlite3.Rc.t -> ('a,'a) monad_fun +(** [lift_err e] is equivalent to [fail e] when [e] is not a success + value, and otherwise returns the monad's values unchanged. + + {b NOTE}: You may be tempted to define a function like + [lift : (Sqlite3.stmt -> Sqlite3.Rc.t) -> ('a,'a) monad_fun] + which would take a function and apply [lift_err (f S) V S] + to the function. However, the partial application [lift f] + would leave you with a {i weak type}, which will force your + type to have a fixed type. *) + +(** {1 Execution functions} + +All of these functions will (effectively) exceute {fail} and return +[Failed] on failure. All functions will omit error behavior unless +there is something different across any of them. *) + +val prepare : Sqlite3.db -> string -> 'a -> 'a stmt_m +(** [prepare db stmt v] returns a monad with bundled value [v] and + the statement in [s]. +*) + +val reprepare : Sqlite3.db -> string -> ('a,'a) monad_fun +(** [reprepare db stmt] finalizes [S] and prepares [stmt] in + its place. *) + +val reset : ('a,'a) monad_fun +(** [reset] resets [S] so that it may be executed again. *) + +val step : ('a,'a) monad_fun +(** [step] is equivalent to the Sqlite3 function {step}. + + {b NOTE}: [step] will fail when the statement returns a row. +*) + +val fold : ('a -> ('b,'b) monad_fun) -> 'a list -> ('b,'b) monad_fun +(** [fold f l] applies each element of [l] to make a monadic function [f]. *) + +val getrow : ('a,(unit * rowdata)) monad_fun +(** [getrow] steps [S] and stores the returned row. The value in [S] is + discarded. + + The function returns a tuple with the unit type to interact with + {extract}. +*) + +val exec_extract : ('a -> 'b option) -> ('b -> 'c option) + -> (('d * 'a),('c * 'a)) monad_fun +(** [exec_extract extr conv] extracts a value from the second element in + [V], and then applies [conv] to it. If both were successful, the + function replaces the first element of [V] with the converted + value. *) + +val extract : string -> (Sqlite3.Data.t -> 'b option) + -> (('a * rowdata),('b * rowdata)) monad_fun +(** [extract name f] finds the value in the row with header name [name] + and applies [f] to it. If [f] succeeds then its return value is + stored in [V]. The rowdata is preserved. +*) + +val finalize : 'a stmt_m -> 'a +(** [finalize] raises an exception if the execution failed, and [V] + otherwise. *) + +val bind_values : Sqlite3.Data.t list -> ('a,'a) monad_fun +(** [bind_values l] binds each index of [l] to a positional parameter + in [S]. *) + +val clear_bindings : ('a,'a) monad_fun +(** [clear_bindings] clears any values bound to [S]. *) + +val exec : Sqlite3.db -> string -> unit stmt_m +(** [exec db s] is equivalent to a call to {prepare} followed by {step}. *) + +val reexec : Sqlite3.db -> string -> ('a,'a) monad_fun +(** [reexec db s] is equivalent to [reprepare >>$ step]. *) + +val bsrc : Sqlite3.Data.t list -> ('a,'a) monad_fun +(** [bsrc l] is equivalent to [bind_values >>$ step >>$ reset >>$ clear_bindings]. *) |
