uncomplicate.fluokitten.core

Contains core Fluokitten categorical functions. This is the
namespace that you want to use or require in your projects that use
Fluokitten built-in functionality or the functionality of various other
libraries that implement Fluokitten protocols.
Intended use: use or require this namespace and other namespaces that
contain the implementations of the protocols, by default jvm.

<*>

(<*> af)(<*> af av)(<*> af av & avs)
Performs a Haskell-style left-associative fapply
on its arguments. (<*> f g h) is equivalent to
(fapply (fapply f g) h). It always uses a two-argument fapply.

If only two arguments are supplied, it is equivalent to fapply.
When called with one argument, creates a function
that can accept the rest of the arguments and apply <*>.

<=<

(<=< f)(<=< f g)(<=< f g & hs)
Composes monadic functions from right to left, same as comp,
in the reverse order than >=>.

>=>

(>=> f)(>=> f g)(>=> f g & hs)
Composes monadic functions from left to right, in the reverse
order from comp. The composed functions threads the calls
through >>=.

>>=

(>>= monadic)(>>= monadic f)(>>= monadic f & fs)
Performs a Haskell-style left-associative bind
on its arguments. (>>= f g h) is equivalent to
(bind (bind f g) h). It always uses a two-argument bind.

If only two arguments are supplied, it is equivalent to bind.
When called with one argument, creates a function
that can accept the rest of the arguments and apply >>=.

bind maintains an implicit context, so >>= too supports
functions that depend on it, such are return and unit.

arity

(arity f)

bind

(bind f)(bind monadic f)(bind monadic monadic2 & args)
Takes a value inside the context of a monad (monadic value)
and a function f that takes a normal value (without the
context) and produces the result inside of a context
of the monadic type.

If called with more arguments, the last argument should be the
function f, and all previous arguments,
monadics will be used as arguments to the function
f. When called with one argument only, produces a function
with f fixed, so it just accepts monadic values and feeds
them to f.

For nested bind calls, there is a syntactic sugar, the
mdo macro.

bind can be also thought of as a function that combines
two computations into one large computation.

The behavior is largely constrained by the laws that should be
satisfied by any monad in regard to the behavior
or bind and pure (see the doc for
uncomplicate.fluokitten.protocols/Monad)

bind maintains an implicit context, and supports
functions that depend on it, such are return and unit.

Some common Clojure constructs that are Monads:
- persistent collections
- reducibles
- nil
- atoms, refs

---- Example with collections:
(bind [1 2 3] (comp list inc))
=> [2 3 4]

---- Example with atoms:
(bind (atom 1) (comp atom inc))
=> #<Atom: 2>

bind!

(bind! f)(bind! monadic f)(bind! monadic monadic2 & args)
An impure, heretic variant of bind that sacrifices kittens to C++ gods.

curry

(curry f)(curry f arity)
Creates an automatically curried version of the function f.
If arity is supplied, the function will be automatically
curried when called with less arguments. If arity is not
supplied, the default arity will depend on the arity of f.
arity defaults to 2 if f can support it, otherwise it is
1.

---- Example: currying +
(((curry +) 3) 5)
=> 8

((((curry + 3) 3) 5) 7)
=> 15

((curry +) 3 5 7)
=> 15

fapply

(fapply af)(fapply af av)(fapply af av & avs)
Applies the function(s) inside af's context to the value(s)
inside av's context while preserving the context. Both contexts
should be of the same (or compatible) type, and the type of
the resulting context is determined by av's type.
af and af stand for "applicative functor function"
and "applicative functor value".

Returns an applicative functor instance consisting of
the result of applying the function(s) inside af's context
to the value(s) inside the av's context. Vararg version
applies the function(s) inside af to the value(s)
provided by the avs' contexts. If called with only one argument,
lifts av so it can be applied to an applicative functor,
i.e creates a new function that can reach inside
the applicative functor's context and return the result
of applying the original context af.

fapply can be thought of as fmap that, instead of
plain function f receives one or many functions inside
the context af, extracts those functions from the context
and applies them to the values inside the context av.

The behavior is largely constrained by the laws that should be
satisfied by any applicative functor in regard to the behavior
or fapply and pure (see the doc for
uncomplicate.fluokitten.protocols/Applicative)

Some common Clojure constructs that are Applicative functors:
- persistent collections
- reducibles
- nil
- atoms, refs

---- Example 1: Clojure collections are applicative functors

(fapply [inc dec] [1 2 3])
=> [2 3 4 0 1 2]

---- Example 2: atoms are applicative functors
(fapply (atom inc) (atom 1))
=> 2

fapply!

(fapply! af)(fapply! af av)(fapply! af av & avs)
Impure, possibly destructive, version of fapply.
Typically reuses the argument functor for the result.
Convenient for functors such as Java arrays, primitive vectors, matrices, etc.
Since this function is not puritan anyway, the implementation does not have
to insist that the contexts of av and af are exactly the same.
It is enough if the implementation of av can handle the similar
context for af. For example, av could be a ref while ag is an atom,
or av is a primitive array, while af is an array of function objects.
Be warned, Haskell people will complain mercilessly.

fmap

(fmap f functor)(fmap f)(fmap f functor & functors)
Applies a function f to the value(s) inside functor's context
while preserving the context. More about Functors can be found
in the doc for uncomplicate.fluokitten.protocols/Functor.

Returns a functor instance consisting of the result of applying f
to the value(s) inside the functor's context. Vararg version applies
f to value(s) provided by the functors' contexts. If called with only
one argument, lifts function f so it can be applied to functor,
i.e creates a new function that can reach inside the functor's
context and return the result of applying the original function f.

fmap can be thought of in two ways:
1. As a function that takes a function f and functor and then maps
   the function over the functor value. In this sense, it is similar
   to ubiquitous map function, with the difference that fmap works
   on any Functor instance and it preserves the context type (while
   map always converts its source to a sequence).
2. As a function that takes a function f so it can operate on functor
   values instead on plain values.

Function f should work on plain values without regard to the functor.
Functor must be an extension of Functor protocol and MUST satisfy
the functor laws
(see the doc for uncomplicate.fluokitten.protocols/Functor)

Some common Clojure constructs that are Functors:
- persistent collections
- reducibles
- functions
- nil
- atoms, refs
- strings
- keywords
- all Objects. (fmap f o) equals (f o) if nothing more specific has
  been defined for object's type

---- Example 1: Clojure collections are functors

(fmap str [1 2 3])
=> ["1" "2" "3"]

Since clojure vector is a functor, it represents a context for its
elements. Function inc works on the elements of the vector, and
does not know anything about the vector itself. The result is a
vector of transformed elements.

---- Example 2: Clojure functions are functors

((fmap str +) 1 2 3)
=> "6"

In this example, + is a context for its arguments. fmapping str
function over + functor (which is also a function), we get another
function that applies string to an argument, but with the context of
incrementing preserved.

---- Example 3: lifting a function
((fmap str) [1 2 3])
=> ["1" "2" "3"]

fmap!

(fmap! f x)(fmap! f x y)(fmap! f x y z)(fmap! f x y z w)(fmap! f x y z w & ws)
Impure, possibly destructive, version of fmap.
Typically reuses the argument functor for the result.
Convenient for functors such as Java arrays,
primitive vectors, matrices, etc.
Be warned, Haskell people will curse through the skies,
since this function is incompatible with their holy scriptures.

fold

(fold x)(fold f x)(fold f init x)(fold f init x y)(fold f init x y z)(fold f init x y z w)(fold f init x y z w & ws)
Folds all the contents of a foldable context by either
getting the single element or if there are more than one
elements in the context by combining them all in the one
aggregate value. How exactly these elements
are combined depends on the actual context. Collections,
that are often used as contexts, require that the elements
are monoids, so they can be easily combined using op.

Some common Clojure constructs that are Foldable:
- persistent collections
- reducibles
- nil
- atoms, refs
- all objects are foldable in a sense that
  (fold o) => o if there is no specific implementation

Some common Clojure constructs that are Monoids:
- persistent collections
- reducibles
- functions
- nil
- strings
- keywords
- numbers

---- Example: vector is foldable, while a set of real
numbers form a monoid with a binary operation + and identity
element 0. Thus,
(fold [1 2 3])
=> 6

foldmap

(foldmap g)(foldmap g x)(foldmap f g x)(foldmap f init g x)(foldmap f init g x y)(foldmap f init g x y z)(foldmap f init g x y z w)(foldmap f init g x y z w & ws)
Folds the contest of a foldable context by applying
function f on each of its elements to produce a monoid
and then uses the operation op of that monoid to combine
the elements into a single aggregate value.
See the doc for fold, the only difference is that foldmap
can fold foldables that contain elements that are not
monoids, by using function f to transform them to monoids
before folding.

If called with only one argument, f, creates a function
that can fold a foldable that contains non-monoid values
by first using f to convert them to monoids.

id

(id x)
Returns the identity element of the monoid that x is
an element of.

---- Example 1: numbers
(id 3)
=> 0

---- Example 2: strings
(id "something")
=> ""

join

(join monadic)
Flattens multiple monads nested in monadic into a single
flat monad that contains ordinary, non-monadic value.

---- Example with collections:
(join [[1 2] [3 4]])
=> [1 2 3 4]

---- Example with atoms:
(join (atom (atom (atom 1))))
=> #<Atom: 1>

join!

(join! monadic)
When surrounded by Haskell comandos, take out this sibling of join. 

just

Creates the context of Maybe monad and puts
the supplied value in it.

maybe?

(maybe? x)
Checks whether x is an instance of the type Just .

mdo

macro

(mdo bindings body)
A syntactic sugar for gluing together chained bind calls.
The structure of mdo is similar to the structure of let.

bindings should be a vector of symbol - expression pairs
in the form [sym1 exp1 sym2 exp2 ...].
while the body should be an expression that uses these
symbols. Body is not wrapped in an implicit do block, so
if multiple forms are needed in the block, they have to
be explicitly wrapped with do.

If the bindings vector is empty, there are no bindings and
no bind function calls, mdo simply evaluates body in that
case.

(mdo [x some-monadic-value
      y some-other-monadic-value]
  some-expression)

expands to:

(bind some-monadic-value
      (fn [x]
        (bind some-other-monadic-value
              (fn [y]
                some-expression))))))

bind maintains an implicit context, so mdo too supports
functions that depend on it, such are return and unit.

---- Example:
(mdo [a [1 2]
      b [4 5]
      c [7]]
  (return (* a b c)))

=> [28 35 56 70]

op

(op)(op x)(op x y)(op x y z)(op x y z w)(op x y z w & ws)
Applies the monoid operation op determined by the type
of monoids x and y. Since op is closed on that monoid,
the result is also in the same monoid and can be further
combined by op with other elemens of the same monoid.
The vararg version is equivalent with (op (op x y) z),
but the actual algorithm for a given monoid depends
on the implementation. For example, (+ 1 2 3) is used
for numbers instead of (+ (1 2) 3)
---- Example 1: numbers as monoids
(op 1 2 3)
=> 6
---- Example 2: strings ar monoids
(op "some" "thing")
=> "something"

pure

(pure applicative)(pure applicative x)(pure applicative x & xs)
Takes any value x and wraps it in a minimal, default, context
of the same type as the context of the applicative value.

If called with only one argument, creates a pure function that
can wrap any value into a specific default context determined
by applicative.

The behavior is largely constrained by the laws that should be
satisfied by any applicative functor in regard to the behavior
or fapply and pure (see the doc for
uncomplicate.fluokitten.protocols/Applicative)

Has context-agnostic versions that take the applicative context
implicitly from the environment: return and unit.

---- Example 1: putting a number in a pure vector context
(pure [] 1)
=> [1]

(pure [] 1 2 3)
=> [1 2 3]

---- Example 2: a number in a pure curried function context:
((pure curried 1) 17)
=> 1

return

(return x)(return x & xs)
A monad-agnostic version of pure, it is equivalent to
(pure <current context>). Valid only inside
a context-aware *time-dependent* dynamic scope.
Otherwise, an IllegalArgumentException will be thrown
complaining that there is no implementation found for
class clojure.lang.Var$Unbound.
The context is available inside the execution of bind
method (and the methods and macros that use it internaly,
such as >>= mdo), or inside the with-context macro.
Also equivalent to the unit function.

---- Example 1:
(defn f [x] (return (inc x)))
(bind [1 2 3] f)
=> [2 3 4]
(bind (just 1) f)
=> 2

---- Example 2:
(f 1)
=> IllegalArgumentException
(with-context []
  (f 1))
=> [1]

--- Example 3:
(with-context []
  (return 1 2 3))
=> [1 2 3]

unit

The same as return.