AST-47 List functions in AS, inspired by SML Basis library#139
AST-47 List functions in AS, inspired by SML Basis library#139matthewhammer merged 34 commits intomasterfrom
Conversation
samples/collections/list.as
Outdated
| case (?(_,t)) { last<T>(t) }; | ||
| } | ||
| }; | ||
| */ |
There was a problem hiding this comment.
@crusso @rossberg @nomeata
Is there a reason that each AssertE expression types as T.unit and not T.Any?
That decision seems to make the function above, from the SML Basis, impossible to type in AS. While this function may not be a great design for AS, due to the lack of exception handling, it still seems useful (and practical for many dev workflows) for a program to fail dynamically while it statically inhabits any type.
There was a problem hiding this comment.
Update: Talked to Claudio on Slack about this; will file an issue shortly.
There was a problem hiding this comment.
Not sure how Any would help, that's the top type, so only compatible with itself. You probably meant None, the bottom type, but a function cannot have that type and ever return.
We probably should have an unreachable expression.
There was a problem hiding this comment.
Right; Claudio clarified elsewhere (on Slack) that we'd want None and not Any here.
OK.
samples/collections/thunk.as
Outdated
| // type error, expression of type | ||
| // () -> (T/23, S/4) | ||
| // cannot produce expected type | ||
| // () -> ((T/23, S/4)) |
There was a problem hiding this comment.
I think I've encountered this before and worked around it. Will try to find an example.
There was a problem hiding this comment.
Not sure if it's the same issue, but here I was expecting the return type of the lambda to be () and had to ascribe (())
func traverse_<A>(f : A -> (), xs : List<A>) {
foldl<A, ()>(func (_ : (), x : A) : (()) {
f(x);
}, (), xs);
};
There was a problem hiding this comment.
Ah, interesting. Thanks!
BTW: Do you know if there's an existing issue (did you make one?); if not, I'll make a new one.
There was a problem hiding this comment.
I couldn't find one so I assume that I forgot.
There was a problem hiding this comment.
That's working as intended. We have n-ary parameters and results and first-class tuples, but they are not the same thing, even though they are coerced implicitly. But still, (T,U) -> (T,U) is a different type from ((T,U)) -> ((T,U)) (mainly because the coercion isn't possible in the polymorphic case).
There was a problem hiding this comment.
Hmm.. I see. Thanks for that explanation. I was able to fix the code to avoid this error.
Aside (not critical)
This "n-ary result" design does not match my mental "notional machine" very well, which is based on CBPV. In CBPV, I make sense of n-ary arguments as being CBPV "currying". Like the functions here, "ordinary currying" in CBPV does not permit partial application.
However, CBPV is asymmetric: Although functions generally take many inputs, each sub-computation has one result. Categorically, I think opetopes have the same structure (zero or more inputs, and one output), though I don't know category theory very well.
Having said all that, I'll try to evolve my mental model now ;)
There was a problem hiding this comment.
Oh, I absolutely agree with you. It would be great if we didn't need to make this distinction. Unfortunately, there is no efficient way to implement it such that it works with type abstraction if you want to raise function arity in the implementation. (That has been a long pain point of many functional languages. See e.g. Ocaml's treatment of datatype constructors -- same thing.)
There was a problem hiding this comment.
Interesting. Yes, pragmatism seems to be at odds with the "nice"/"clean" design, as usual.
FWIW, I interpret data constructors in CBPV as being sugar for value types, and never standing in for computation type arrows, except if they get "promoted" (eta expanded) by a "real" lambda. That agrees with my (limited) understanding of OCaml constructors vs OCaml functions, but I may be wrong.
samples/collections/list.as
Outdated
| ?(x, l); | ||
|
|
||
| // get head of list | ||
| func hd<T>(l : List<T>) : ?T = { |
There was a problem hiding this comment.
I'd be less penurious and name these head and tail.
But to be honest, I wonder how useful these are without exceptions. Matching on the list itself is less verbose than matching on the option.
There was a problem hiding this comment.
OK, sounds fine to me.
(In general, I have no desire to choose the names of library functions. I have no real preferences, and mostly just want to be told what naming conventions to follow. That goes for all of the naming nitpicks lower down, too. I tried to follow the SML conventions where they made sense, though I now see that I deviated in some places; it wasn't very intentional.)
|
|
||
|
|
||
| // polymorphic linked lists | ||
| type List<T> = ?(T, List<T>); |
There was a problem hiding this comment.
How about using a record {head, tail}, which would be nicer esp for pattern matching? Currently, records are a bit annoying because you have to write new, but I have some sugar in mind for allowing to omit that.
There was a problem hiding this comment.
One argument for tuples would be that it is less efficient (records need more memory and more time to look up fields because of polymorphism). Of course, programmer ergonomics often trump run-time efficiency, but it is a pity that we can’t have both.
There was a problem hiding this comment.
Yeah, you're probably right. Some day somebody will propose "final" object types. :)
There was a problem hiding this comment.
I don't see how records, with their heavier syntax, are "nicer" for matching a pair.
Am I missing something?
There was a problem hiding this comment.
Well, let's say more self documenting. Also, we should probably allow label punning in patterns, as most other langs.
There was a problem hiding this comment.
OK, I anticipate hating the version of this file (list.as) where all the patterns on the LHS take 2 or 3 times their current length, but I'm certainly willing to try it, to find out.
There was a problem hiding this comment.
Note we don't have record patterns yet.
There was a problem hiding this comment.
Haha, Ok. Thanks for that note.
There was a problem hiding this comment.
Hah, excellent point. I don't even remember why why.
Anyway, in that case, keeping it a pair is probably better for now. Sorry for the noise.
samples/collections/list.as
Outdated
| case (?(_,t)) { last<T>(t) }; | ||
| } | ||
| }; | ||
| */ |
There was a problem hiding this comment.
Not sure how Any would help, that's the top type, so only compatible with itself. You probably meant None, the bottom type, but a function cannot have that type and ever return.
We probably should have an unreachable expression.
samples/collections/list.as
Outdated
| }; | ||
|
|
||
| // get tail of list, as an optional list | ||
| func tlo<T>(l : List<T>) : ?List<T> = { |
There was a problem hiding this comment.
If we really want to have these functions then we should at least decide for one version. I'd prefer the optional one.
There was a problem hiding this comment.
Yep, OK.
I had both because until you fixed the type checker bug, only one worked (viz., the "stranger" one that uses tlo, which we can drop now).
There was a problem hiding this comment.
Could we allow question marks in identifiers? The tl and tl? would be nice variations... alternatively try_tl rather than tlo ?
There was a problem hiding this comment.
Interesting idea.
In this case, I just dropped the versions that raise exceptions (per @rossberg's comment), so there's no need to have two different names, at least not here.
Do we anticipate other situations where we need two versions for the same operation (fail-via-exception vs optional return)? Don't we just always just prefer options in those cases?
There was a problem hiding this comment.
Allowing question marks in ids would require using spaces for the option type, though (? Nat etc). Maybe not a big problem, but I could see that as a very frequent source of surprise and confusion.
And Schemers would probably object to using f? for something else then predicates. :)
samples/collections/list.as
Outdated
| */ | ||
|
|
||
| // last element, optionally; tail recursive | ||
| func lasto<T>(l : List<T>) : ?T = { |
There was a problem hiding this comment.
Same as above, I think we should only have one version.
There was a problem hiding this comment.
OK. I'll prefer the versions that use optional returns, as discussed elsewhere.
|
|
||
| // Thunks are not primitive in AS, | ||
| // ..but we can encode them as objects with a force method: | ||
| type Thk<T> = {force:() -> T}; |
There was a problem hiding this comment.
I don't have a strong feeling here, but I prefer to write t.force() and not t ().
The latter form is more concise, but it also makes the forces in the code harder to locate; so I don't see it as a real benefit. I like these operations to be very explicit, for inspecting the "laziness" of each purportedly lazy algorithm by just looking for the word "force".
There was a problem hiding this comment.
I think I'm not sure what you intend this for. Is it even worth introducing a name for this? Don't know that any other library would have it. The name force would rather suggest a lazy suspension, but then you need a different type.
|
|
||
| // type Stream<T> = | ||
| // ??? Sh<T> or Osh<T> | ||
| // Q: Which is more more "conventional?" |
There was a problem hiding this comment.
You want to allow empty streams, so it must be the latter. I'd define
type Stream<T> = ?{head : T; next : () -> Stream<T>}
There was a problem hiding this comment.
Ok, that def sounds fine to me, but why not just use a pair?
(What's the advantage of using records for pairs? Just readability, or something more?)
There was a problem hiding this comment.
I'm beginning to sense we might want to add non-extensible records for documentation and efficiency.
I expect the same thing will happen for variants so we can do efficient jump tables...
|
|
||
| // Thunks are not primitive in AS, | ||
| // ..but we can encode them as objects with a force method: | ||
| type Thk<T> = {force:() -> T}; |
There was a problem hiding this comment.
Why not simply Thunk<T> = () -> T?
There was a problem hiding this comment.
Haha. What is your convention for preferring records with named fields vs no records and no named fields?
- Pairs should be records
- Unpaired functions should be just functions
?
samples/collections/thunk.as
Outdated
| // type error, expression of type | ||
| // () -> (T/23, S/4) | ||
| // cannot produce expected type | ||
| // () -> ((T/23, S/4)) |
There was a problem hiding this comment.
That's working as intended. We have n-ary parameters and results and first-class tuples, but they are not the same thing, even though they are coerced implicitly. But still, (T,U) -> (T,U) is a different type from ((T,U)) -> ((T,U)) (mainly because the coercion isn't possible in the polymorphic case).
| // cannot produce expected type | ||
| // () -> ((T/23, S/4)) | ||
|
|
||
| func pair<T,S>(x:Thk<T>, y:Thk<S>) : Thk<(T,S)> { |
There was a problem hiding this comment.
Not sure I get what this is for. Seems less convenient then a literal pair.
There was a problem hiding this comment.
Laziness. A thunk producing a pair is not the same as a pair of thunks.
There was a problem hiding this comment.
Oh, I see, I missed the thunkification of the result.
Is this worth having? It seems very specialised. I'd suggest not making the lib too sweeping for now.
There was a problem hiding this comment.
Sure, this thunk module can be dropped. It's more of an experiment of me using actorscript than a useful module for others.
OTOH, streams, or other lazy structures (beyond mere thunks) may be more useful.
67ae247 to
5a9149f
Compare
… as boolean lists
| }; | ||
|
|
||
| ///////////////////////////////////////////////////////////////////////////////// | ||
|
|
There was a problem hiding this comment.
As everyone may or may not be aware, the compiler's front end steps (lexer and parser) do not recognize words, or even the types for words. Ultimately, when these concepts are supported, we want to use them for hashes and short (word sized) bit strings.
Until then, I'm using linked lists of booleans.
There was a problem hiding this comment.
I'm a little confused. The interpreter does support words, it's just the compiler that doesn't yet.
There was a problem hiding this comment.
Yes. I should have looked in prelude.ml more carefully.
Commits: [dfinity-lab/common@7278afe2...6f8f0311](https://github.com/dfinity-lab/common/compare/7278afe2b6ddcd0c78c82fae38160bc4583fc1a6...6f8f03113b16177e35c9ac7ea3448e3a4aa2d055) * [422f8ec5](https://github.com/dfinity-lab/common/commit/422f8ec5d23e0ceae4db28ede0f1be578a87ea65) unpacker: stop trampling (#138) * [3f4d3077](https://github.com/dfinity-lab/common/commit/3f4d307796b48c535f7cd2c2eb6c9298c5387928) nix: specify a sha256 for fetching sources.nix * [4d317b75](https://github.com/dfinity-lab/common/commit/4d317b75180773cdd70a5189e7ffab295c96edd8) Merge pull request #139 from dfinity-lab/basvandijk/specify-sha256-for-sources.nix * [6f8f0311](https://github.com/dfinity-lab/common/commit/6f8f03113b16177e35c9ac7ea3448e3a4aa2d055) INF-1023: Run benchmarks on CI
Commits: [dfinity-lab/common@7278afe2...6f8f0311](https://github.com/dfinity-lab/common/compare/7278afe2b6ddcd0c78c82fae38160bc4583fc1a6...6f8f03113b16177e35c9ac7ea3448e3a4aa2d055) * [422f8ec5](https://github.com/dfinity-lab/common/commit/422f8ec5d23e0ceae4db28ede0f1be578a87ea65) unpacker: stop trampling (#138) * [3f4d3077](https://github.com/dfinity-lab/common/commit/3f4d307796b48c535f7cd2c2eb6c9298c5387928) nix: specify a sha256 for fetching sources.nix * [4d317b75](https://github.com/dfinity-lab/common/commit/4d317b75180773cdd70a5189e7ffab295c96edd8) Merge pull request #139 from dfinity-lab/basvandijk/specify-sha256-for-sources.nix * [6f8f0311](https://github.com/dfinity-lab/common/commit/6f8f03113b16177e35c9ac7ea3448e3a4aa2d055) INF-1023: Run benchmarks on CI
## Changelog for motoko-base: Branch: next-moc Commits: [caffeinelabs/motoko-base@27b7d097...0375b45d](caffeinelabs/motoko-base@27b7d09...0375b45) * [`f9f5de90`](caffeinelabs/motoko-base@f9f5de9) Revert "Remove WordN.toInt ([dfinity-lab/motoko-base#125](http://r.duckduckgo.com/l/?uddg=https://github.com/dfinity-lab/motoko-base/issues/125))" and reimplement ([dfinity-lab/motoko-base#137](http://r.duckduckgo.com/l/?uddg=https://github.com/dfinity-lab/motoko-base/issues/137)) * [`09f2f2ec`](caffeinelabs/motoko-base@09f2f2e) Push built documentation to GH pages ([dfinity-lab/motoko-base#78](http://r.duckduckgo.com/l/?uddg=https://github.com/dfinity-lab/motoko-base/issues/78)) * [`b15c0a0d`](caffeinelabs/motoko-base@b15c0a0) Docs for TrieMap module ([dfinity-lab/motoko-base#128](http://r.duckduckgo.com/l/?uddg=https://github.com/dfinity-lab/motoko-base/issues/128)) * [`012bacec`](caffeinelabs/motoko-base@012bace) Document more of Trie module; clean up. ([dfinity-lab/motoko-base#130](http://r.duckduckgo.com/l/?uddg=https://github.com/dfinity-lab/motoko-base/issues/130)) * [`f635a5c7`](caffeinelabs/motoko-base@f635a5c) Document TrieSet module ([dfinity-lab/motoko-base#139](http://r.duckduckgo.com/l/?uddg=https://github.com/dfinity-lab/motoko-base/issues/139)) * [`08f167de`](caffeinelabs/motoko-base@08f167d) doc comments ([dfinity-lab/motoko-base#141](http://r.duckduckgo.com/l/?uddg=https://github.com/dfinity-lab/motoko-base/issues/141))
## Changelog for motoko-base: Branch: next-moc Commits: [caffeinelabs/motoko-base@27b7d097...0375b45d](caffeinelabs/motoko-base@27b7d09...0375b45) * [`f9f5de90`](caffeinelabs/motoko-base@f9f5de9) Revert "Remove WordN.toInt ([dfinity-lab/motoko-base#125](http://r.duckduckgo.com/l/?uddg=https://github.com/dfinity-lab/motoko-base/issues/125))" and reimplement ([dfinity-lab/motoko-base#137](http://r.duckduckgo.com/l/?uddg=https://github.com/dfinity-lab/motoko-base/issues/137)) * [`09f2f2ec`](caffeinelabs/motoko-base@09f2f2e) Push built documentation to GH pages ([dfinity-lab/motoko-base#78](http://r.duckduckgo.com/l/?uddg=https://github.com/dfinity-lab/motoko-base/issues/78)) * [`b15c0a0d`](caffeinelabs/motoko-base@b15c0a0) Docs for TrieMap module ([dfinity-lab/motoko-base#128](http://r.duckduckgo.com/l/?uddg=https://github.com/dfinity-lab/motoko-base/issues/128)) * [`012bacec`](caffeinelabs/motoko-base@012bace) Document more of Trie module; clean up. ([dfinity-lab/motoko-base#130](http://r.duckduckgo.com/l/?uddg=https://github.com/dfinity-lab/motoko-base/issues/130)) * [`f635a5c7`](caffeinelabs/motoko-base@f635a5c) Document TrieSet module ([dfinity-lab/motoko-base#139](http://r.duckduckgo.com/l/?uddg=https://github.com/dfinity-lab/motoko-base/issues/139)) * [`08f167de`](caffeinelabs/motoko-base@08f167d) doc comments ([dfinity-lab/motoko-base#141](http://r.duckduckgo.com/l/?uddg=https://github.com/dfinity-lab/motoko-base/issues/141))
## Changelog for candid: Branch: Commits: [dfinity/candid@47366bab...2abea024](dfinity/candid@47366ba...2abea02) * [`2abea024`](dfinity/candid@2abea02) Typos ([dfinity/candid#139](http://r.duckduckgo.com/l/?uddg=https://github.com/dfinity/candid/issues/139))
## Changelog for candid: Branch: Commits: [dfinity/candid@47366bab...2abea024](dfinity/candid@47366ba...2abea02) * [`2abea024`](dfinity/candid@2abea02) Typos ([dfinity/candid#139](http://r.duckduckgo.com/l/?uddg=https://github.com/dfinity/candid/issues/139))
## Changelog for ic-hs: Branch: master Commits: [dfinity/ic-hs@2c9f2ea8...80875f3a](dfinity/ic-hs@2c9f2ea...80875f3) * [`8f47bec4`](dfinity/ic-hs@8f47bec) provisional_create_canister_with_cycles takes an optional specified_id ([dfinity/ic-hs#126](https://github.com/dfinity/ic-hs/issues/126)) * [`af73f215`](dfinity/ic-hs@af73f21) Implement ic0.mint_cycles in ic-hs ([dfinity/ic-hs#127](https://github.com/dfinity/ic-hs/issues/127)) * [`cb9b35d6`](dfinity/ic-hs@cb9b35d) Support requests to a subnet ID ([dfinity/ic-hs#128](https://github.com/dfinity/ic-hs/issues/128)) * [`4cd1c3d3`](dfinity/ic-hs@4cd1c3d) charge canister http_request based on target subnet ([dfinity/ic-hs#130](https://github.com/dfinity/ic-hs/issues/130)) * [`5f07313f`](dfinity/ic-hs@5f07313) replace base64 by ascii endpoint in canister http tests ([dfinity/ic-hs#131](https://github.com/dfinity/ic-hs/issues/131)) * [`9607be0c`](dfinity/ic-hs@9607be0) omit ic-ref binary in ic-ref-test artifact ([dfinity/ic-hs#132](https://github.com/dfinity/ic-hs/issues/132)) * [`67029cb8`](dfinity/ic-hs@67029cb) RUN-509: Enable Canister Timers in pre-upgrade ([dfinity/ic-hs#134](https://github.com/dfinity/ic-hs/issues/134)) * [`52736f33`](dfinity/ic-hs@52736f3) add test for timer in post-upgrade on stopped and stopping canister ([dfinity/ic-hs#133](https://github.com/dfinity/ic-hs/issues/133)) * [`ed328b87`](dfinity/ic-hs@ed328b8) implement canister range checks in ic-ref-test ([dfinity/ic-hs#135](https://github.com/dfinity/ic-hs/issues/135)) * [`e29764e9`](dfinity/ic-hs@e29764e) fix conditions on read_state requests ([dfinity/ic-hs#136](https://github.com/dfinity/ic-hs/issues/136)) * [`ebedfe6e`](dfinity/ic-hs@ebedfe6) make nonexisting canister id in the subnet's ranges ([dfinity/ic-hs#137](https://github.com/dfinity/ic-hs/issues/137)) * [`80875f3a`](dfinity/ic-hs@80875f3) increase error msg length limit ([dfinity/ic-hs#139](https://github.com/dfinity/ic-hs/issues/139))
## Changelog for ic-hs: Branch: master Commits: [dfinity/ic-hs@2c9f2ea8...80875f3a](dfinity/ic-hs@2c9f2ea...80875f3) * [`8f47bec4`](dfinity/ic-hs@8f47bec) provisional_create_canister_with_cycles takes an optional specified_id ([dfinity/ic-hs#126](https://github.com/dfinity/ic-hs/issues/126)) * [`af73f215`](dfinity/ic-hs@af73f21) Implement ic0.mint_cycles in ic-hs ([dfinity/ic-hs#127](https://github.com/dfinity/ic-hs/issues/127)) * [`cb9b35d6`](dfinity/ic-hs@cb9b35d) Support requests to a subnet ID ([dfinity/ic-hs#128](https://github.com/dfinity/ic-hs/issues/128)) * [`4cd1c3d3`](dfinity/ic-hs@4cd1c3d) charge canister http_request based on target subnet ([dfinity/ic-hs#130](https://github.com/dfinity/ic-hs/issues/130)) * [`5f07313f`](dfinity/ic-hs@5f07313) replace base64 by ascii endpoint in canister http tests ([dfinity/ic-hs#131](https://github.com/dfinity/ic-hs/issues/131)) * [`9607be0c`](dfinity/ic-hs@9607be0) omit ic-ref binary in ic-ref-test artifact ([dfinity/ic-hs#132](https://github.com/dfinity/ic-hs/issues/132)) * [`67029cb8`](dfinity/ic-hs@67029cb) RUN-509: Enable Canister Timers in pre-upgrade ([dfinity/ic-hs#134](https://github.com/dfinity/ic-hs/issues/134)) * [`52736f33`](dfinity/ic-hs@52736f3) add test for timer in post-upgrade on stopped and stopping canister ([dfinity/ic-hs#133](https://github.com/dfinity/ic-hs/issues/133)) * [`ed328b87`](dfinity/ic-hs@ed328b8) implement canister range checks in ic-ref-test ([dfinity/ic-hs#135](https://github.com/dfinity/ic-hs/issues/135)) * [`e29764e9`](dfinity/ic-hs@e29764e) fix conditions on read_state requests ([dfinity/ic-hs#136](https://github.com/dfinity/ic-hs/issues/136)) * [`ebedfe6e`](dfinity/ic-hs@ebedfe6) make nonexisting canister id in the subnet's ranges ([dfinity/ic-hs#137](https://github.com/dfinity/ic-hs/issues/137)) * [`80875f3a`](dfinity/ic-hs@80875f3) increase error msg length limit ([dfinity/ic-hs#139](https://github.com/dfinity/ic-hs/issues/139))
## Changelog for ic-hs: Branch: master Commits: [dfinity/ic-hs@2c9f2ea8...80875f3a](dfinity/ic-hs@2c9f2ea...80875f3) * [`8f47bec4`](dfinity/ic-hs@8f47bec) provisional_create_canister_with_cycles takes an optional specified_id ([dfinity/ic-hs#126](https://github.com/dfinity/ic-hs/issues/126)) * [`af73f215`](dfinity/ic-hs@af73f21) Implement ic0.mint_cycles in ic-hs ([dfinity/ic-hs#127](https://github.com/dfinity/ic-hs/issues/127)) * [`cb9b35d6`](dfinity/ic-hs@cb9b35d) Support requests to a subnet ID ([dfinity/ic-hs#128](https://github.com/dfinity/ic-hs/issues/128)) * [`4cd1c3d3`](dfinity/ic-hs@4cd1c3d) charge canister http_request based on target subnet ([dfinity/ic-hs#130](https://github.com/dfinity/ic-hs/issues/130)) * [`5f07313f`](dfinity/ic-hs@5f07313) replace base64 by ascii endpoint in canister http tests ([dfinity/ic-hs#131](https://github.com/dfinity/ic-hs/issues/131)) * [`9607be0c`](dfinity/ic-hs@9607be0) omit ic-ref binary in ic-ref-test artifact ([dfinity/ic-hs#132](https://github.com/dfinity/ic-hs/issues/132)) * [`67029cb8`](dfinity/ic-hs@67029cb) RUN-509: Enable Canister Timers in pre-upgrade ([dfinity/ic-hs#134](https://github.com/dfinity/ic-hs/issues/134)) * [`52736f33`](dfinity/ic-hs@52736f3) add test for timer in post-upgrade on stopped and stopping canister ([dfinity/ic-hs#133](https://github.com/dfinity/ic-hs/issues/133)) * [`ed328b87`](dfinity/ic-hs@ed328b8) implement canister range checks in ic-ref-test ([dfinity/ic-hs#135](https://github.com/dfinity/ic-hs/issues/135)) * [`e29764e9`](dfinity/ic-hs@e29764e) fix conditions on read_state requests ([dfinity/ic-hs#136](https://github.com/dfinity/ic-hs/issues/136)) * [`ebedfe6e`](dfinity/ic-hs@ebedfe6) make nonexisting canister id in the subnet's ranges ([dfinity/ic-hs#137](https://github.com/dfinity/ic-hs/issues/137)) * [`80875f3a`](dfinity/ic-hs@80875f3) increase error msg length limit ([dfinity/ic-hs#139](https://github.com/dfinity/ic-hs/issues/139))
(This is a cleaner version of PR #128)