Witchcraft is a library providing common algebraic and categorical abstractions to Elixir.
(Monoids, functors, monads, arrows, and categories)
A big thank you to Brandon Labbé for creating the logo to this project
README
Table of Contents
Quick Start
def deps do
[{:witchcraft, "~> 0.5"}]
end
Relationship to Other Packages
Quark TypeClass
↘ ↙
Witchcraft
↓
Algae
- Quark: Standard combinators (
id,compose, &c) - TypeClass: Used internally to generate type classes
- Algae: Algebraic data types that implement Witchcraft type classes
Hierarchy
Semigroupoid Semigroup Setoid Foldable Functor -----------┐
↓ ↓ ↓ ↓ ↙ ↓ ↘ |
Category Monoid Ord Traversable Apply Bifunctor |
↓ ↙ ↘ ↓
Arrow Applicative Chain Extend
↘ ↙ ↓
Monad Comonad
It is very common to want everything in a chain. You can import the entire chain
with use. For example:
use Witchcraft.Monad
Any options that you pass to use will be propagated all the way down the chain
use Witchcraft.Monad, except: [~>: 2]
Some modules override Kernel operators and functions. While this is generally safe,
if you would like to skip all overrides, pass override_kernel: false as an option
use Witchcraft.Foldable, override_kernel: false
Finally, to import the entire library:
use Witchcraft
Values
Beginner Friendliness
As much as possible, keep things friendly. Concrete examples are available in the source code, and a Wiki is in the roadmap.
Consistency
Language
Elixir does a lot of things differently from other functional languages. The idea
of a data "subject" being piped though functions is conceptually different from
pure composition of functions that are later applied. Witchcraft honours the Elixir
way, and operators point in the direction that data travels.
Concept
By learning from developments in other languages, we can collapse a lot of ideas into
single concepts (liftA === liftM, for instance).
Pedagogy
You shouldn't have to learn another language just to understand powerful abstractions! By enabling people to use a language that they already know, and is already in the same ballpark in terms of values (emphasis on immutability, &c), we can teach and learn faster.
Pragmatism
Convincing a company to use a language like Haskell or PureScript can be challenging. Elixir is gaining a huge amount of interest. Many people have been able to introduce these concepts into companies using Scala, so we should be able to do the same here.
Compatibility
Witchcraft works with Algae, providing Witchcraft
instances for all Algae data types. There is nothing stopping you from writing your
own implementations for other data types.
Testing
Each structure is provided a set of rules that it must obey. For convenience, Witchcraft
includes property tests to ensure that datatypes that you write are easily property testable
for adherence to their laws. Full compatibility with QuickCheck is coming soon.
Differences from Haskell
Naming
Some functions have been renamed for clarity, generality, or style.
| Prelude + Control (Haskell) | Witchcraft (Elixir) |
|---|---|
<> | `< |
fmap | lift |
liftA | lift |
liftA2 | lift |
liftA3 | lift |
liftM | lift |
liftM2 | lift |
liftM3 | lift |
apply | seq |
<*> | <<~ (reverse ~>>) |
*> | seq_second |
<* | seq_first |
pure | wrap |
return | wrap |
<$> | <~ (reverse ~>) |
>> | seq_first |
>>= | >>> |
=<< | <<< |
Hierarchy
Having a clean slate, we have been able to use a very clean of typeclasses. Strictly,
all Applicatives are Functors, and all Monads are Applicatives. This grants
us the ability to reuse functions in their child classes. For example, pure can
be used for return, liftA* is the same as liftM*, and so on (see chart above).