# FunLand
[![hex.pm version](https://img.shields.io/hexpm/v/fun_land.svg)](https://hex.pm/packages/fun_land)
[![Build Status](https://travis-ci.org/Qqwy/elixir_fun_land.svg?branch=master)](https://travis-ci.org/Qqwy/elixir_fun_land)
FunLand adds Behaviours to define [Algebraic Data Types](https://en.wikipedia.org/wiki/Algebraic_data_type) ('Container' data types) to Elixir, including many helpful operations with them. Where applicable, an ADT implementation for Elixir's built-in types like Lists, Maps, Strings and Functions are included.
Also included are some implementations of commonly-used ADTs, for your leisure. _(These might be split off in their own library in the future)_
FunLand is based on ideas of the [Fantasy Land](https://github.com/fantasyland/fantasy-land) JavaScript specification for Algebraic Data Types, as well as the implementations of ADTs in other languages, such as [Haskell](haskell.org) and [Idris](http://idris-lang.org/).
FunLand attempts to use understandable names for the different behaviours and functions, to make ADTs as approachable to newcomers as possible.
### Pre-release version
As can be seen below in the roadmap, FunLand is not fully finished yet. New pre-release versions might introduce backwards-incompatible changes.
Mostly lacking are:
- Enough documentation.
- Tests for most of the example implementations in `FunLand.Builtin.*`.
### Changelog
- 0.9.3 - Fixes bug that made it impossible to compile on Elixir 1.8.x
- 0.9.2 - Numbers v5.0.0 support
- 0.9.1 - Fixes dispatching of Builtin Structs to proper behaviour implementation modules. Adds Combinable and Reducable implementations for MapSet.
- 0.9.0 - Split off FunLandic to its own library.
- 0.8.0 - Important (backwards-incompatible) naming and functionality changes. Implementation of Traversable. Implementations for the SuccessTuple type.
### Roadmap
- [x] The most commong Algebraic Data Types, built as Behaviours that can be added to your own modules/structs:
- [x] *Mappable* - any structure you can `map` over: changing the contents without changing the structure.
- [x] *Appliable* - any Mappable structure you can combine two of, where the first contains a function to `apply_with` the contents of the second, returning a new strucure.
- [x] *Applicative* - any Appliable structure that can be created from any value you want to `wrap` inside.
- [x] *Chainable* - any Appliable structure that you can `bind` functions to, which, when given the contents of the structure, return a new version of the structure.
- [x] *Monad* - Anything structure that is both Applicative and Chainable, which makes them super flexible!
- [x] Monadic do-notation. (The implementation is heavily based on code from the [monad](https://github.com/rmies/monad) library. Lots of thanks!)
- [x] _let_ statements inside the monadic do-notation.
- [x] *Semicombinable* - Anything which, when you have two of them, you can `combine` them together into one.
- [x] *Combinable* - Anything that is Combinable, and also has a `neutral` value which you can combine something with when you don't have anything else, to keep the result the same.
- [x] *CombinableMonad* - Any structure that is both a Monad and Combinable.
- [x] *Reducable* - Any structure that can be `reduce`d to a single value, when given a Combinable (or alternatively, a starting value and a function to combine this with a single value inside the structure).
- [x] Traversable
- [x] Find out how to implement Traversable.traverse properly in a dynamically typed language. (How do you know what empty structure to return when being passed an empty structure?) -> Pass explicit extra parameter with result module.
- [x] Also, where to put these practical implementations? -> FunLandic.*
- [x] How to write proper code for the built-in types like List? (What to put in the monadic syntax? etc.)
- [ ] Catcheable exceptions instead of raised strings.
- [x] Implement some practical Algebraic Data Types to show what can be done with them:
- [x] List - the list we all know and love.
- [x] Maybe - either just filled with something, or empty (nothing inside)
- [x] Reader - store a state in a reader monad and refer to it only when you need it later on.
- [x] Writer - Keep a log of the things that happened alongside your computations.
- [x] A Custom Behaviour you can expand upon yourself, with your own log-appending mechanism.
- [x] IOListWriter, which logs using an IOList (an implementation of the writer behaviour that is useful in most common circumstances).
- [x] Sum - Combine any Mappable filled with numbers by summing them.
- [x] Product - Combine any Mappable filled with numbers by multiplying them.
- [x] Any - Combine any Mappable filled with booleans by checking if some property is true for at least one of them.
- [x] All - Combine any Mappable filled with booleans by checking if some property is true for all of them.
- [x] Either/Result - Contains two results, returns the first result of the two that is not empty.
- [x] SuccessTuple implementation of Either/Maybe! Wow!
- [ ] Fully write this readme.
- [ ] Extend documentation.
- [ ] More Fruit Salad explanations.
- [ ] Write as many tests as possible.
- [ ] Revisit+extend code examples.
### Later Future:
- [ ] Comonad
- [ ] Improve documentation, better fruit salad descriptions?
## Installation
The package is available on [hex](https://hex.pm/packages/fun_land) and can can be specified as a dependency by adding the snippet below in your `mix.exs`.
```elixir
def deps do
[{:fun_land, "~> 0.9.2"}]
end
```