Akh 3 – The Splittening
Akh so! Akh 3 is out now.
$ npm install --save akh
Links
Akh is a Javascript collection of monads and monad transformers inspired by MTL. Version three brings some new types to the party, breaks the collection up into a set of proper npm packages, and gives the API a quick dusting. Let’s take a quick look at the key changes.
Cleaner API
Back in the bad old Akh 2 days, you had to write imports like this:
// Akh 2
const EitherT = require('akh').trans.either
Akh 3 simplifies imports and namespaces so that you now write:
// Akh 3
const EitherT = require('akh').EitherT
// or even
import {EitherT} from 'akh'
The old require('akh').base
helper functions have also now all been moved to top level exports:
// Akh 2
const liftM = require('akh').base.liftM
// Akh 3
const liftM = require('akh').liftM
Also, the names of the various run/extract methods have been simplified and you can now even use them as methods:
// Akh 2
const List = require('akh').type.list
List.runList(List.of(2))
// Akh 3
const List = require('akh').List
List.run(List.of(2))
// or even
List.of(2).run()
Packages for Everything
The core akh
npm package still wraps up all your favorite types, such Either
and Cont
, but you can now also consume those types through individual npm packages:
// Use Either as part of main Akh library
const Either = require('akh').Either
// Only import just the Either type
const Either = require('akh.either').Either
This allows specifying lighter-weight, more targeted dependencies. It should also make it easier to maintain and iterate on the core type implementations (he says optimistically), and make it easier to extend Akh.
Here’s the list of official types and their packages, as of version 3.1:
- akh.cont – Continuations
- akh.dcont – Delimited continuations
- akh.either – Either
- akh.error – Error
- akh.identity – Identity
- akh.list – List
- akh.maybe – Maybe
- akh.reader – Reader
- akh.state – State
- akh.unique – Unique
- akh.writer – Writer
Maybe, Reader, and Writer
Akh 3.1 brings friends Reader
, Writer
, and Maybe
into the core collection, along with their transformer progenitors ReaderT
, WriterT
, and MaybeT
.
Maybe
and MaybeT
from akh.maybe should be familiar enough. MaybeT
extends an underlying value to support optional values while Maybe
brings this logic on its own. Here’s a classic example:
const Maybe = require('akh').Maybe
const safeDiv = (x, y) =>
y === 0 ? Maybe.nothing : Maybe.just(x / y)
Maybe.just(3)
.chain(x => safeDiv(12, x))
.map(x => x * x)
.maybe('default') === 16 // extract value or return 'default' if none
Maybe.just(0)
.chain(x => safeDiv(12, x))
.maybe('default') === 'default'
Reader
and ReaderT
from akh.reader allow reading from a shared environment:
const Reader = require('akh').Reader
Reader.asks(r => r.a)
.map(x => x * 2),
.run({ a: 10, b: 3 }) === 20
Writer
and Writer
from akh.write allow producing a value along with a list of output values:
const Writer = require('akh').Writer
const List = require('akh').List;
const r = Writer.tell(List.of(1)) // append to output
.censor(x => x.concat(List.of(5))) // modify output
.map(_ => 'result')
.run(List.zero)
r.value === 'result'
r.output.run() == [1, 5] // Extract array from the List using `run()`
Issues / Feedback
So if you wish your Javascript had some monad transformers, give Akh a try. (Admittedly, that target market may be close to one, but oh well.)
Please let me know if you run into any problems, have any suggestions, or would like to contribute to Akh’s development. I’ve also tried to clean up the documentation to make it easier to get started.