Skip to content

Instantly share code, notes, and snippets.

@dyokomizo
Last active January 1, 2016 16:29
Show Gist options
  • Save dyokomizo/8171478 to your computer and use it in GitHub Desktop.
Save dyokomizo/8171478 to your computer and use it in GitHub Desktop.
We have three data types:
- Name and Password, both with String representations;
- Account, a Name and Password pair.
Given that each data type can have its invariants, we have some functions, representing morphisms from the data type to its representation (M is some Monad, like Maybe/Either/Validation, it's not important which):
- stringToName :: String -> M Name
- nameToString :: Name -> String
- stringToPassword :: String -> M Password
- passwordToString :: Password -> String
- pairToAccount :: (Name, Password) -> M Account
- accountToPair :: Account -> (Name, Password)
The constructor functions may fail (hence the Maybe/Either/Validation monad) but the representation projections don't.
So far we can have each datatype and respective morphisms on its own module, completely independent.
To build an Account from a pair of Strings we just use a couple combinators:
- pairOfStringsToAccount = pairToAccount <=< (stringToName *** stringToPassword)
Here <=< [1] is the right-to-left Kleisli composition of monads and *** [2] is the Arrow split combinator (which can be used because every Monad can be seen as a Kleisli Arrow).
1. http://hackage.haskell.org/package/base-4.6.0.1/docs/Control-Monad.html#v:-60--61--60-
2. http://hackage.haskell.org/package/base-4.6.0.1/docs/Control-Arrow.html#v:-42--42--42-
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment