@@ -29,8 +29,11 @@ namespace purescript {
2929
3030 class boxed : public std::shared_ptr<void> {
3131
32− using fn = std::function<boxed(const boxed&)>;
33− using eff_fn = std::function<boxed(void)>;
32+ public:
33+ using fn_t = std::function<boxed(const boxed&)>;
34+ using eff_fn_t = std::function<boxed(void)>;
35+ using dict_t = std::map<const string, boxed>;
36+ using array_t = std::deque<boxed>;
3437
3538 public:
3639 using std::shared_ptr<void>::shared_ptr;
@@ -52,54 +55,71 @@ namespace purescript {
5255
5356 boxed(const std::nullptr_t) : std::shared_ptr<void>() {
5457 }
55−
56− boxed(std::initializer_list<boxed> l) : std::shared_ptr<void>(std::make_shared<std::deque<boxed>>(l)) {
58+
59+ boxed(array_t&& l) : std::shared_ptr<void>(std::make_shared<array_t>(std::move(l))) {
5760 }
5861
59− boxed(std::initializer_list<std::pair<const string, boxed>> m) : std::shared_ptr<void>(std::make_shared<std::map<string, boxed>>(m)) {
62+ boxed(dict_t&& m) : std::shared_ptr<void>(std::make_shared<dict_t>(std::move(m))) {
6063 }
6164
6265 template <typename T,
6366 typename = typename std::enable_if<!std::is_same<boxed,T>::value>::type>
6467 boxed(const T& f,
65− typename std::enable_if<std::is_assignable<std::function<boxed(boxed)>,T>::value>::type* = 0) : std::shared_ptr<void>(std::make_shared<fn>(f)) {
68+ typename std::enable_if<std::is_assignable<std::function<boxed(boxed)>,T>::value>::type* = 0) : std::shared_ptr<void>(std::make_shared<fn_t>(f)) {
6669 }
6770
6871 template <typename T,
6972 typename = typename std::enable_if<!std::is_same<boxed,T>::value>::type>
7073 boxed(const T& f,
71− typename std::enable_if<std::is_assignable<std::function<boxed(void)>,T>::value>::type* = 0) : std::shared_ptr<void>(std::make_shared<eff_fn>(f)) {
74+ typename std::enable_if<std::is_assignable<std::function<boxed(void)>,T>::value>::type* = 0) : std::shared_ptr<void>(std::make_shared<eff_fn_t>(f)) {
7275 }
7376
7477 template <typename T,
7578 typename = typename std::enable_if<!std::is_same<boxed,T>::value &&
76− std::is_convertible<T,fn>::value>::type>
79+ std::is_convertible<T,fn_t>::value>::type>
7780 auto operator=(const T& right) -> boxed& {
7881 if (std::shared_ptr<void>::operator bool()) {
79− auto& f = *static_cast<fn*>(get());
82+ auto& f = *static_cast<fn_t*>(get());
8083 f = right;
8184 } else {
82− reset(new fn(right));
85+ reset(new fn_t(right));
8386 }
8487 return *this;
8588 }
8689
8790 auto operator()(const boxed& arg) const -> boxed {
88− auto& f = *static_cast<fn*>(get());
91+ auto& f = *static_cast<fn_t*>(get());
8992 return f(arg);
9093 }
9194
9295 auto operator()() const -> boxed {
93− auto& f = *static_cast<eff_fn*>(get());
96+ auto& f = *static_cast<eff_fn_t*>(get());
9497 return f();
9598 }
9699
97− auto operator[](const char key[]) const -> boxed {
98− const auto& dict = *static_cast<const std::map<const string, boxed>*>(get());
100+ auto operator[](const char key[]) const -> const boxed& {
101+ const auto& dict = *static_cast<const dict_t*>(get());
99102 return dict.at(key);
100103 }
101104
102− };
105+ auto operator[](const char key[]) -> boxed& {
106+ auto& dict = *static_cast<dict_t*>(get());
107+ return dict[key];
108+ }
109+
110+#ifdef NDEBUG
111+ auto operator[](const int index) const -> const boxed& {
112+ const auto& array = *static_cast<const array_t*>(get());
113+ return array[index];
114+ }
115+#else
116+ auto operator[](const int index) const -> const boxed& {
117+ const auto& array = *static_cast<const array_t*>(get());
118+ return array.at(index);
119+ }
120+#endif // NDEBUG
121+
122+ }; // class boxed
103123
104124 template <typename T, typename... Args>
105125 inline auto box(Args&&... args) -> boxed {
@@ -112,6 +132,12 @@ namespace purescript {
112132 return unboxed;
113133 }
114134
135+ template <typename T,
136+ typename = typename std::enable_if<!std::is_same<T, const boxed&>::value>::type>
137+ constexpr auto unbox(const T value) -> T {
138+ return value;
139+ }
140+
115141 template <typename T>
116142 inline auto peek(boxed& b) -> T& {
117143 auto& unboxed = *static_cast<T*>(b.get());
@@ -123,12 +149,10 @@ namespace purescript {
123149 return box<T>(unbox<T>(b));
124150 }
125151
126− using fn_t = std::function<boxed(const boxed&)>;
127− using dict_t = std::map<const string, boxed>;
128− using array_t = std::deque<boxed>;
129−
130− using as_array = std::initializer_list<boxed>;
131− using as_dict = std::initializer_list<std::pair<const string, boxed>>;
152+ using fn_t = boxed::fn_t;
153+ using eff_fn_t = boxed::eff_fn_t;
154+ using dict_t = boxed::dict_t;
155+ using array_t = boxed::array_t;
132156
133157 constexpr auto undefined = nullptr;
134158