Commit | Line | Data |
---|---|---|
d45d190d SK |
1 | [![Build Status](https://travis-ci.org/ibnfirnas/hope.svg?branch=master)](https://travis-ci.org/ibnfirnas/hope) |
2 | ||
07bb8aec SK |
3 | Hope |
4 | ==== | |
a11ea326 SK |
5 | |
6 | A quest for a "standard" library with uniform, composable abstractions. | |
d2ab44d2 | 7 | |
07bb8aec SK |
8 | Originally motivated by a desire for an error monad and generic option type |
9 | operations, and stood for _Higher Order Programming in Erlang_. Soon after, I | |
10 | wished all standard containers used consistent conventions and protocols (such | |
11 | as consistent accessor names, argument positioning rules and expression of | |
12 | semantics with option and result types). | |
d2ab44d2 | 13 | |
07bb8aec SK |
14 | Here lies an experiment to see what something like that could look like. As all |
15 | proper experiments should, this one is used daily in production projects (hence | |
16 | the high-ish version number, 'cause semver). | |
d2ab44d2 | 17 | |
07bb8aec SK |
18 | |
19 | Conventions | |
20 | ----------- | |
21 | ||
22 | I entertain any forward-thinking library design ideas, but more than anything | |
23 | else, these are influenced by Jane Street's Core of the OCaml world. | |
24 | ||
25 | - A module per data type implementation | |
26 | - Name of the module is the name of the type | |
27 | - Inside the module, the type it implements is always named t(..), such as: | |
28 | `hope_foo:t()`, _not_ `hope_foo:foo()` | |
29 | - t(..) is always the first argument | |
30 | - Names of private records _may_ be short, such as: `#foo{}` or `#t{}` (Though | |
31 | I'm second-guessing this idea, since seeing `{t, ..}` in stack traces is less | |
32 | than helpful. I'm considering requiring fully-qualified names for all record | |
33 | definitions and maybe short-handing what would've been `#t{..}` as | |
34 | `-define(T, ?MODULE). -record(?T, {..}).`, which may be a bit ugly. Still | |
35 | thinking...) | |
36 | - Names of public records _must_ be fully qualified, such as: `#hope_module_record{}` | |
37 | - Names of all modules _must_ be fully qualified, such as: `hope_module` (this | |
38 | should go without saying, but just to be sure...) | |
39 | ||
40 | ||
41 | Abstractions | |
42 | ------------ | |
43 | ||
44 | ### Monads | |
45 | ||
46 | A class of burritos, used for sequencing operations on a particular data type. | |
d2ab44d2 SK |
47 | Defined in `hope_gen_monad`, implemented as: |
48 | ||
49 | - `hope_result`: for composition of common functions returning | |
50 | `{ok, Val} | {error, Reason}`. An alternative to exceptions, which makes the | |
51 | error conditions apparent in the spec/signature. Analogous to Haskell's | |
52 | `Data.Either a b`, Jane Street Core's (OCaml) `('a, 'b) Result.t`, Rust's | |
53 | `Result<T, E>` | |
54 | - `hope_option`: for expressing and composing the intention that the value may | |
55 | or may not be available. An alternative to the common `undefined` (which is | |
56 | equivalent to the dreaded `null`). Analogous to ML's (SML, OCaml, etc) | |
57 | `'a Option.t`, Rust's `Option<T>` and Haskell's `Data.Maybe a` [1]. | |
58 | ||
59 | ||
07bb8aec | 60 | ### Containers |
d2ab44d2 | 61 | |
07bb8aec SK |
62 | A class of abstract data types to which we have exclusive access and can put |
63 | things in and take them out. See issue #9 | |
64 | ||
65 | - Operations on all abstract types of containers _should_ share a common lexicon | |
66 | - Concrete implementations of an abstract data type _must_ be swapable | |
67 | ||
68 | #### Dictionary | |
d2ab44d2 SK |
69 | |
70 | Defined in `hope_gen_dictionary`, implemented as: | |
71 | ||
72 | - `hope_kv_list`. Equivalent to orddict/proplist. Operations implemented with | |
73 | BIFs from `lists` module, where possible | |
74 | ||
07bb8aec SK |
75 | TBD: |
76 | - `hope_hash_tbl`. API around stdlib's `dict` | |
77 | - `hope_gb_dict`. API around stdlib's `gb_trees` | |
78 | ||
79 | #### Set | |
80 | ||
81 | TBD: | |
82 | - `hope_hash_set`. API around stdlib's `sets` | |
83 | - `hope_gb_set`. API around stdlib's `gb_sets` | |
84 | ||
85 | #### Queue | |
86 | ||
87 | TBD | |
88 | ||
89 | Should include both FIFO (queue) and LIFO (stack), so that user can swap if a | |
90 | different order is desired. | |
91 | ||
92 | Should we attempt to include priority queues or make them a separate abstract | |
93 | type? | |
94 | ||
95 | #### Sequence | |
96 | ||
97 | TBD | |
98 | ||
99 | Not yet defined and only partially implemented as: | |
100 | ||
101 | - `hope_list` | |
102 | ||
103 | ||
104 | ### Resources | |
105 | ||
106 | A class of abstract systems to which we share access with an unknown number of | |
107 | users and can make requests to perform operations which may not get done for | |
108 | any number of reasons. | |
109 | ||
110 | #### Storage | |
111 | ||
112 | TBD | |
113 | ||
114 | See issue #11 | |
115 | ||
d2ab44d2 SK |
116 | |
117 | [1]: http://en.wikipedia.org/wiki/Option_type |