Last active
April 15, 2017 03:46
-
-
Save ahammel/bea2dc125a422c6789c1d7f4b662ef9c to your computer and use it in GitHub Desktop.
Alpaca type classes (sort of)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| module semigroup | |
| export_type semigroup | |
| export concat | |
| {- Semigroup: anything with an associative operation | |
| Instead of a type class, we define a record type which specifies the | |
| necessary fields. | |
| Inspired by the [object algebra] approach and, more directly, the | |
| [scrap your typeclasses] proposal. | |
| [object alebra approach]: https://www.cs.utexas.edu/~wcook/Drafts/2012/ecoop2012.pdf | |
| [scrap your typeclasses]: http://www.haskellforall.com/2012/05/scrap-your-type-classes.html | |
| -} | |
| type semigroup 'a = { append: fn 'a 'a -> 'a } | |
| {- Reduce a list by appending, starting with a default value. | |
| Polymorphic functions take an instance of the `semigroup`. | |
| In this particular case it would be better if instances of the semigroup | |
| class could override the default implementation. (The semigroup instance of | |
| `option`, for instance, can short-circuit evalute.) I'm not sure how to | |
| implement that, however. | |
| -} | |
| let concat iSemigroup x [] = x | |
| let concat iSemigroup x y::ys = | |
| match iSemigroup with | |
| {append=f} -> concat iSemigroup (f x y) ys |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| module monoid | |
| export_type monoid | |
| export concat | |
| {- Class for types with an associate operation and an identity element. | |
| Of note: `monoid` is an implicit sub-type of `semigroup`. Any `monoid` | |
| instance counts as a `semigroup` instance as well because it has an | |
| `append` field with the right type (yay row polymorphism!). | |
| It might be nice to be able to make the type hierarchy explicit with a | |
| syntax like this: | |
| ```type monoid 'a = {empty: 'a | semigroup 'a }``` | |
| -} | |
| type monoid 'a = {empty: 'a, append: fn 'a 'a -> 'a} | |
| let concat iMonoid xs = | |
| match iMonoid with | |
| {empty=e} -> semigroup.concat iMonoid e xs | |
| -- ^ taking advantage of that row-polymorphism |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| module list | |
| export append | |
| let append [] ys = ys | |
| let append (x::xs) ys = x :: (append xs ys) | |
| {- Monoid instance for lists -} | |
| let monoid () = {append=append, empty=[]} | |
| test "monoid.concat flattens nested lists" = | |
| assert.equal [:scrap, :your, :typeclasses] | |
| (monoid.concat (monoid ()) [[:scrap, :your], [], [:typeclasses]]) | |
| test "a monoid instance can be used as a semigroup instance" = | |
| assert.equal [:scrap, :your, :typeclasses] | |
| (semigroup.concat (monoid ()) [:scrap] [[:your], [], [:typeclasses]]) | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| module int | |
| {- You can define multiple instances without newtype wrappers. | |
| Full disclosure: rebar dies rather than running this file for me. | |
| -} | |
| let addition () = {empty=0, append=fn x y -> x + y} | |
| let multiplication () = {empty=1, append=fn a b -> a * b} | |
| test "addition works" = | |
| assert.equal 6 (monoid.concat (addition ()) [1,2,3]) | |
| test "multiplication works" = | |
| assert.equal 9 (monoid.concat (multiplication ()) [1, 3, 3]) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment