Let's Build a Cloudflare Worker with WebAssembly and Haskell
blog.cloudflare.com
blog.cloudflare.com
1. Content delivery (downloads).
2. Analytics (metrics and logging).
3. Proxy misc HTTP requests.
I planned to move web-hosting to Workers too but Netlify is just too smooth and I don't see a reason to do so currently, though the recently announced free analytics product (for websites proxied through Cloudflare) might tempt me to do so anyway.
[0] The 50ms time-limit is for cpu-time and not wall-time. The latter doesn't seem to have any documented limits and so works great for "streaming" network-bound workloads.
But man - Haskell feels really difficult to wrap my mind around. Could anyone here comment on the learning curve and how it affected productivity for team adoption? Seems like it's on the more difficult side of things.
There are some tricks that you need to express more complicated computation but they get more attention than use.
Also there is the whole type theory rabbit hole that you'll fall down a few times until you understand where you want to be. The trick is to accept that the model is a simplification and rather than being as precise as possible find out where you can get away with simplifications.
Overall I’d recommend it!
Experience: Mercury (bank)‘a backend is 100% Haskell
I think Haskells problems breakdown into 3 distinct areas. The community, the conventions and the language itself.
Firstly the community can be hostile to a new comer. The documentation and tutorials for various libraries is often incomplete, outdated and written in a hard to grok plain text document. Asking questions can also be painful as there’s definitely a tinge of elitism to some of the power members.
Secondly, the conventions that are often encouraged go against writing clear and understandable code. Function names are small. You have interface functions (doThis) that exist just to call private functions (doThis’).
These odd conventions get compounded by a lot of warts on the language itself.
So finally onto the language itself.
There’s a lot of operators to keep track of. None of which do what you expect. And the ones you do expect, like dot notation, don’t exist until you turn on a language feature flag.
For feature flags there’s a standard set of 20 that every experienced Haskeller turns on but good luck finding that out as a beginner, and good luck finding out that’s why the example isn’t working for you.
There’s also 3 different types of String, all of them in active use by different libraries, which you have to manually cast between often.
And the dev environment can be hard to figure out. Error messages are difficult to grok. The repl often breaks. And you sometimes run into hidden libraries that are in your project but arent accessable until you import them.
Honestly it’s a mess and this is before I touch on the unique parts of a pure functional language like Haskell. Which is a shame because Haskell brings to the table some serious super powers. They’re just not worth the hit to developer productivity in a team setting.
> The documentation and tutorials for various libraries is often incomplete, outdated and written in a hard to grok plain text document
I am keen to make an effort to remove outdated documentation and to complete incomplete documentation. If you give specific examples I shall try to do so.
> Asking questions can also be painful as there’s definitely a tinge of elitism to some of the power members.
Could you say which forums you discovered "elite power members"? For example, was it Reddit, Haskell-Cafe mailing list, #haskell IRC channel, Discord server?
> Secondly, the conventions that are often encouraged go against writing clear and understandable code. Function names are small. You have interface functions (doThis) that exist just to call private functions (doThis’).
For better or worse, that's the way the community likes to program. I'm not sure there's much I can do about that unless you have specific examples of code that could be rewritten to be clearer.
> These odd conventions get compounded by a lot of warts on the language itself.
Did you have any specific warts in mind?
> For feature flags there’s a standard set of 20 that every experienced Haskeller turns on but good luck finding that out as a beginner, and good luck finding out that’s why the example isn’t working for you.
Were there specific "feature flags" (called "extensions" in GHC) that you needed to turn on but that the compiler didn't tell you that you needed to turn on? That's uncommon (though it is possible, OverloadedStrings is one such example).
Which examples did you try that didn't work because they didn't mention which extensions needed to be enabled? If you report them to me I will try to get them fixed upstream.
> The repl often breaks
Could you say more about in which way the repl ("GHCi") often breaks?
> And you sometimes run into hidden libraries that are in your project but arent accessable until you import them.
Could you say more? That sounds like something that could well be true but I can't see how it's a problem. You have to import libraries in many languages (Julia, Python, ...). What went wrong here?
Thanks for any light you may be able to shed.
But there's no way you could get a team to adopt it. Too many non-Haskellers will make up claims about needing to know category theory in order to do anything. Or it's academic, or design-by-committee.
Someone commented earlier about Haskell having solutions to problems that only Haskell has, and I can give you a couple of examples:
1) Famously it has the Maybe type - instead of null - for dealing with possibly-missing values. In Haskell, if you want to chain together operations without checking for the presence of each value, you use ">>=". As many people have noted before, this is a cryptic symbol. You can just use JavaScript instead which has ".?".
2) It has mechanisms for cleaning up resources in the case you want to cancel something while it's running, notably ResourceT. Other languages take the approach where you simply cannot cancel a thread/future, thus preventing you from needing to write cleanup code in the first place.
There's also the problem of its community. Rather that accept information second-hand I invite you to read a few posts from https://www.reddit.com/r/haskell/ and see for yourself how it treats newcomers.
I should also mention the type system. As any dynamic typing enthusiast will tell you, statically-typed languages are too verbose. And Haskell is too terse. So it kind of loses on both fronts there. You'll need to contend with people who don't like type systems because they get in your way, rather than helping you out. When I'm feeling lazy and I can't think of what to write, I just write "Int" instead and then let the compiler tell me what I was supposed to write, e.g. "Topic -> SequenceNum -> Value -> IO a0".
src/Server/Paxos/Learner.hs:41:68: error:
• Couldn't match expected type ‘Topic
-> SequenceNum -> Value -> IO a0’
with actual type ‘Int’
• In the third argument of ‘learnService’, namely ‘callback’
In the second argument of ‘(.)’, namely
‘learnService myId topicLocks callback’
In the ‘learn’ field of a record
|
41 | pure $ Learner { learn = liftIO . learnService myId topicLocks callback }
|
God knows how I managed to read that cryptic error message though.