TotalMap-0.1.0.0: README.md
Total Map
===============
Often one may have an enum type representing all possible keys of something, and wishes to store some data associated with it. In this case you have two options - use a function or a Map from containers. A function works, but can be difficult to update and has not Eq or Show instances. A map solves this issue, but gives no guarantee that a key has associated data - all functions become partial. This library offers a different way of solving this problem.
A `TotalMap k a` is a total mapping from a key of type `k` to a value of type `a`; each `k` will have exactly one `a`. It permits many instances, including `Show` and `Eq`.
Example
------
Let us create and example. We start with some imports and some language pragmas.
```haskell
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
import TotalMap
import Control.Lens
import Control.Monad (void)
import Data.Functor.Rep (tabulate)
import qualified GHC.Generics as GHC (Generic)
import Generics.SOP
```
TotalMap uses generics-sop internally, so we require it as an import. We also require some typeclasses introduced by lens.
For our example, we shall create a dummy program for sending out peoples fortunes based on their star sign. We shall create a star sign type.
```haskell
data StarSign
= Aries
| Taurus
| Gemini
| Cancer
| Leo
| Virgo
| Scorpio
| Sagittarius
| Capricorn
| Aquarius
| Pisces
deriving (Eq, Show, GHC.Generic, Generic)
```
Note the derivation of both `GHC.Generic` and `Generic`. These are required to guarantee that `StarSign`'s constructors take no imports.
We have a list of people, and we can partition them based on their star sign.
```haskell
data Date = Date
{ month :: Int
, day :: Int
} deriving (Eq, Show)
data Person = Person
{ name :: String
, email :: String
, birthDate :: Date
} deriving (Eq, Show)
signFromDate :: Date -> StarSign
signFromDate = undefined
peopleSign :: [Person] -> TotalMap StarSign [Person]
peopleSign ps = tabulate $ \s -> filter ((==) s . signFromDate . birthDate) ps
```
We could send people an email with their fortune.
```haskell
sendFortune :: String -> String -> StarSign -> IO ()
sendFortune = undefined
sendFortunes :: [Person] -> IO ()
sendFortunes =
void .
itraverse (\sign -> mapM_ (\p -> sendFortune (name p) (email p) sign)) .
peopleSign
```
Future
-----
* Come up with a better example
* Is Lens necessary. It is useful, but it is a huge dependency.
The following is required to make tests compile.
```haskell
main :: IO ()
main = return ()
```