README
A ReasonML/OCaml library for category theory and abstract algebra.
Documentation
See documentation
Installation
Bucklescript/ReasonML
Install the project:
yarn install bs-bastet --save
And add the dependency to your bs-dependencies in bsconfig.json
:
"bs-dependencies": [
"bs-bastet"
]
The project will be available under the Bastet
namespace
Native
Install the project:
opam install bastet
Examples
# #require "bastet";;
# open Bastet;;
# module T = Functors.ListF.Option.Traversable;;
module T = Bastet.Functors.ListF.Option.Traversable
# T.sequence [Some "foo"; Some "bar"];;
- : string list option = Some ["foo"; "bar"]
# Functors.ListF.Int.Show.show [1; 1; 2; 3; 5; 8];;
- : string = "[1, 1, 2, 3, 5, 8]"
Suggested Usage
Use kliesli composition
The monadic equivalent of the |>
operator is flat_map
(>>=
). Both are very useful for writing
code that's easy to reason about as data all flows in one direction.
However, function composition (>.
) and kliesli composition for monads (>=>
) are often underused
in code. Composing functions and monads monoidally like this in a concatenative style can make a
codebase easier to read and can also prevent devs on the team from duplicating code.
Consider a typical use case. Often in a codebase you have something that fetches a value that may or
may not exist ('a option
). Splitting out this code into smaller functions and combining (and
reusing) them with composition leads a lean code style:
# let ((>=>)) = Option.Infix.((>=>));;
val ( >=> ) : ('a -> 'b option) -> ('b -> 'c option) -> 'a -> 'c option =
<fun>
# type form = { name: string; address: string option };;
type form = { name : string; address : string option; }
# let get_form () =
(* Assume some side effect got the form here *)
Some { name = "Foo"; address = Some "123 Bar St." };;
val get_form : unit -> form option = <fun>
# let get_address form = form.address;;
val get_address : form -> string option = <fun>
# let get_form_address = get_form >=> get_address;;
val get_form_address : unit -> string option = <fun>
# get_form_address ();;
- : string option = Some "123 Bar St."
Instantiated Functors
For interfaces based on functors, use already instantiated functors if available to avoid the extra boilerplate:
# Functors.ArrayF.Int.Additive.Fold_Map.fold_map
- : ('a -> int) -> 'a array -> int = <fun>
Don't Overuse Infix
Don't overuse infix operators. If the code is combinatorial it can make it more readable, but in a lot of cases the prefix operators are simpler and easier to read. If you do use infix operators, prefer local opens over global opens to avoid polluting the toplevel:
# let trim_all strings =
let open List.Infix in
StringLabels.trim <