Is Haskell a good choice for software security?
typeable.io
typeable.io
That feature is the explicit typing of effects via monads. Just look at the recent log4j example: If effects were explicitly typed in Java, you would potentially scratch your head why you need a network monad or a "insert code into the process" effect to just log a line.
Of course, in current Haskell, everything is put into the same IO monad. But in principle, I think that effect systems could have a very nice effect on software security.
>
> That feature is the explicit typing of effects via monads. Just look at the recent log4j example: If effects were explicitly typed in Java, you would potentially scratch your head why you need a network monad or a "insert code into the process" effect to just log a line.
That would not have helped - the network access with RCE was a feature put into the library. What does the language selection have to do with a feature request of "We want evaluated log strings to be able to do network access with RCE"?
There's nothing special in any language (even Haskell) that will prevent this sort of thing.
Haskell does not work by aggregating together the features that a whole system needs. It works by breaking down permissions per function. You would immediately see that a function which was only ever meant to do context lookups also has network access. This would be such a crazy type for such a simple function that no one would write it this way.
Don't think about it as aggregating effects, think about it as, all of the leaves of the system have the most narrow permissions possible. And that's where most bugs are, in the leaves.
I might distinguish
resolveFormatString :: String -> [List Parameter] -> IO String"
resolveFormatStringSafe :: String -> [List Parameter] -> String
but it wouldn't be "most narrow permissions possible". It would be "everything or nothing".This way, for one example, you can log in some State-derived monad, keeping logs for caller to extract and use. It is as safe as pure function. And, of course, it is trivial to implement in IO.
The developers of the library would immediately spot that their call does a lot more than it was ever supposed to locally. They would have a function that has a crazy permissive type like IO instead of something very narrow related to the specific functionality they need to do their one lookup.
but the point was that if the feature is intentionally developed, then the type signatures would reflect it - it doesn't do "a lot more than it was ever supposed to".
Type systems don't tell you that a logging library shouldn't access the network. It just tells you that it does, and if this feature was intentional, then how would the type system flag it differently from a cURL-like library that writes to disk with data from the network?
I still don't see how that would help - this logging library was SUPPOSED to have network access. Would a user pause to wonder what the network access is for when it's literally part of the featurelist?
You give functions permissions on a fine-grained basis, permissions which are automatically derived. The specific function which has the bug didn't need network access. It just needed to look something up in the environment. That function would never have a type that gave it network access, that would be insane and a type error.
My reading of the bug and exploit is that the specific function not only needed network access, it was a intentional feature.
> It just needed to look something up in the environment.
That's not how I understand it - it parses the user-supplied input, and fetches (and subsequently executes) the package in the user-supplied input. The environment is irrelevant.
Now, bearing in mind that this was intentionally put in, and that the feature is working as intended and expected, how would a different programming language help?
Even if written in (for example) Haskell, the behaviour will be coded the same way, because that is the intended behaviour.
No one would have wondered anything - it's a networked logger, with network functionality.
Only functions with certain type signatures can do IO in Haskell. This could be broken down to be more granular such that the type system makes it clear (and even somewhat of a burden) to the caller whether writing to disk happens, or network access, or both.
Imagine the entry point to your program is given all "Effects", and then must pass them down the call stack as needed to other functions. Without the appropriate Effect, a function cannot perform the Effect. People might wonder why they were required to pass the NetworkAccess Effect into their logging calls.
NetworkAccess Effect wouldn't be that strange for a logging system that supports multiple networked log managers like syslog.
That said, I'm a bit skeptical that Haskell would have prevented this particular issue in practice. The logging monad would just likely just have been called a LoggingM (in MTL style) and most users would have been oblivious as to exactly what it was doing... and as you say: Logging to a remote system needs the network.
I guess what could have saved a Haskell program here is that there's no such thing as "download code and execute it with the same privileges as you" with being very explicit about that. (E.g. calling 'system' or whatever)
EDIT: Just to say: I don't mean to be flippant.
And i meanr it more in that one part is literally just passing the data along, while the other part generates the data with being fed whatever is needed for it to. so, if yoj want to just log a literal string yoj wouldnt provide any additional functionality to the generator.
if you want it to expand strings, then you provide a function for that. and so on
In Haskell, effectful text parsing is severely frowned upon, so that template language wouldn't get used there. In Python people would frown upon the multi-use function that runs a template engine and logs text when those should be 2 functions. In C people would be up in arms over a logging framework that doesn't log exactly the text you gave it.
In C you would be playing with lots of interesting macros at enterprise level scale, doing Sun RPC calls, encoded in ASN.1, and maybe even manually twerking the generated stubs.
What I mean by this is that you're not tempted to use some arbitrary eval() method on untrustworthy input, nor are you likely to be able to just start reading and running code found some place on disk from a binary-installed app.
The main log4j vuln that's caused an uproar wasn't just that it did some sort of dynamic lookup at run-time, but also that it could then take the result, and run it as attacker-controlled bytecode.
Similarly, a web application that uses say, Python or PHP might have an exploitable vulnerability where the user can upload files. That functionality is going to be intentional, but the problem can crop up that the user can control the upload path, and the application can then execute the uploaded file.
Other vulnerabilities can certainly be written in Haskell, but remote code execution (RCE) vulnerabilities are the sort of jackpot issue that will be much more difficult to pull off there. The same should apply to most languages with a distinct dev-time compilation step, as long as they've got other memory safety controls. (Rust, Go, Ocaml are likely fine as well for instance.)
See https://gmb.is/refinement-types.html for a non-Haskell example.
[0] No, not sanitization!
Java serialization is not what is used by web frameworks. They use JSON deserializing, typically using libraries like Jackson, which are of course fully strongly typed.
Let me put it another way, it doesn't strike me as the best possible example to use.
This is clearly on the past, as an example that once existed.
> Java provided ... there was no way
If anything, that text in misleading people into believing that Java doesn't do it anymore, instead of just nobody using it.
The OP writes,
"Software Security has no universal theory on which to rely. Security is most often taught by enumerating different security issues, mitigations and security models and hoping that students can build from them to gain general understanding. Even of those theoretical works that exist, relatively few of try to build a link between programming language and security aspects."
Compilers and IDEs can improve. Where all the security effort clearly wanes is at the right of the OP's "technical --> tooling --> thinking" spectrum.
A modern language should be memory safe... But general language safety must extend to dependency management and package repositories. Without competent dependency management and fully-secured repositories of vetted code, we still have a professional community of very proud dumpster fires.
Not correct. You can certainly inspect before instantiation:
https://docs.oracle.com/javase/7/docs/platform/serialization...
I think any advocate for Haskell has to justify, at minimum, why it should be preferred to all of Rust/Go/Java/Python for a given use case. These all have way better tooling, developer ergonomics, and library support.
(I don't really like Haskell and think it gets a disproportionate amount of buzz here – but I think most Haskell devs would agree with that last sentence. See all the complaints about stack and cabal on reddit, for example.)
Here's some justification:
- All those languages force me to think imperatively, therefore hamstringing my mind. I don't want to waste time thinking in those languages.
- Haskell has more universal potential. It's obviously a smaller community. BUT I can use Haskell to program FPGAs (clash), embedded systems (Ivory, CoPilot), frontend (ghcjs), write music (tidal, csound-expression, euterpea), shaders & graphics (GPipe, Hylogen), on top of general purpose computing (with a best-in-class FFI to boot.) The nature of the language is such that you can use Haskell for anything and have it still be Haskell - Rust, Go, etc can't get close to that capability.
- None of those languages have tooling at the level of ghci. I've used both Go and Rust extensively and ghci blows their tooling out the water. Cabal is also just excellent nowadays. Haskell also has some of the best testing libraries out there too.
- Haskell has better library support for its community size than those languages. It's substantially easier to find a quality Haskell library on Hackage than a Go one on GitHub. Haskell wins on the quality front, and most gaps imo can be filled easily (API bindings, for instance, are trivial.)
- Developer ergonomics? Haskell's parametric & ad-hoc polymorphism alone combined with its RTS outclass all those languages imo. Go's RTS is worse. All those languages' parametric polymorphism is worse.
^ all this is true IF you have put in a good amount of time becoming a Haskell pro. For beginners, there are arguments against it. But I'm no beginner so why waste my time using that as my litmus test?
I think the argument is that it provides stronger static typing than any of those languages, with only Rust being close out of the other languages that you list. This allows you to encode business logic (incl. security logic) invariants into the type system and catch a lot more errors/bugs at compile time.
The step up from Java to Rust/Haskell in terms of static typing capabilities is at least as big as the step up from python to Java.
edit: Another question. Is there a language that has stronger static typing than Rust without the weird performance pitfalls and subpar tooling that Haskell has? I can imagine a project for which such features would be useful, but getting over those two issues is difficult.
Writing correct code with fewer bugs.
Catching bugs earlier.
Not having to write unit tests for things the compiler can figure out for you, leaving you free to write the actual meaningful tests.
Making code self-documenting with types, leading to less puzzlement.
... just to name a few.
In particular, strong types past some point start exploding code complexity for any kind of polymorphic code. My favorite example is adding strong typing to linear algebra operations, via units of measure for each element of a matrix. Try to find a library that can multiply matrices where each element can be a different physical quantity (of course, validating first that the two matrices can actually be multiplied) - say, multiplying (1m 2s⁻¹) * (2s⁻¹ 1m)ᵀ = 2m/s + 2m/s = 4m/s; but not allowing (1m 2s⁻¹) * (2m 1s⁻¹)ᵀ, since it would be 2m² + 2s⁻².
Even if you can find such a library, it will be significantly more complex than an equivalent linear algebra library that is less strongly typed (one that only handles matrices of numbers, without units of measure).
Whenever I write Python , I wish I was writing Haskell. No need to ask about artificial examples of linear algebra; just my boring day to day code in Python would benefit from having Haskell's type system. And yes, I do know about static typing for Python -- I find it's worse, tooling and effectiveness wise, than an actual static type system.
And the example I gave is not entirely artificial - units of measure are often measured as an advantage of strong type systems, something that could potentially avoid the Ariadne disaster, and I find this common example unconvincing.
> something that could potentially avoid the Ariadne disaster
Haskell or any language with modern static typing would definitely have helped. You wouldn't be mixing unit types and confusing them like it happened (if I remember correctly) with the Ariadne. Would it have been enough? I don't know! But it would have helped! Any measure of static and dynamic analysis would have helped for mission critical software, and it's evident the Ariadne had some serious deficits in this regard.
At least the preference of Haskell vs Python is easy to justify: Haskell has a top-of-class static typing system and Python doesn't, which if you believe static types lead to better code (which I do), makes it clear why you'd prefer former. Whole classes of mistakes which are easy to create inadvertently using Python simply go away (or are very difficult to commit) using Haskell. If you care about code that is correct and with fewer bugs (on a continuum, of course) then that's your justification.
This is hugely subjective but if I'm writing large data transformation pipelines for example, the type system and the compositionsal power of a language like Haskell, or pure FP scala, makes such a task an absolute breeze. It all just slots together like Lego. You have a high degree of confidence that the thing will work, and you can use local reasoning to understand the parts and, by extension the whole program, since the laws of composition and the lazy eval model make this trivial in comparison to imperative code. The way code can compose, the runtime and the resulting local reasoning, can honestly feel like a super power sometimes. Beware of thinking programs written in other languages are simpler to reason about, they might not be. There's more than the "simplicity" of the code to worry about in software.
Is it better than Rust? I can't answer that sort of question, but I can tell you that full-throttled pure FP can be a pretty damn amazing tool when you need it. Rust seems to be a fascinating language for doing, say, systems programming, with some FP-like idioms built in. Amazing! Comparing languages though is tricky, it's always about tradeoffs, context and so on. I don't believe in a hierarchy of languages.
An example: you cannot express in Java "this function does not write to disk", its type system simply doesn't allow it. In order to make sure, you'd have to inspect the code of the function, and the libraries it uses. In Haskell, this is trivial because just by looking at the type of the function you can tell if it's even possible for it to do I/O.
Go requires tons of boilerplate and didn't have generics until recently; there's your answer.
Rust is a bizarre comparison. Haskell predates Rust and Rust takes some (many?) ideas from it or from languages within the same pedigree. Also, I don't know anyone who thinks Rust is "simple", so why ask about this comparison? Write Rust if you want to, no Haskeller is going to complain about your choice.
You ask for a lot of reasons considering the amount you dare to provide. No, nobody has to do that, it doesn't make any sense. Let Rust people comment under articles about Haskell why Rust is the better choice.
I'm not trying to be dense. Are you saying for every programming language you choose, you make an strict ordering of every existing language and then decide which one you'll pick?
Do you think there is a strict ordering of "is better than" between Haskell and Rust?
Examples:
Need to copy a bunch of files? Use bash.
Need to do a quick Monte Carlo simulation? Probably use Python since it allows me to write it the fastest (based on my familiarity).
Need to write drivers? Use C.
I don't think there is a strict ordering of "is better than" between Haskell and Rust. I think for many purposes they are roughly equivalent, and for some one or the other is more suited to the task.
But, if I can't identify any problem for which Haskell is a better tool than Rust, why would I ever learn Haskell?
How would you even decide you want to learn Rust and not Haskell if you didn't know either? Hype? Popularity? Because your coworkers know Rust, or the codebase is in Rust? Those are all good reasons, honestly! So if you were in a Haskell shop, you'd have reason to prefer Haskell over Rust. There's your answer. Either will be better than Python for a medium/large project, but likely worse for a really tiny script or program.
How did you pick Python over Ruby? They are very similar, yet they have many differences. Think about it, and there's another answer for you.
Haskell is good for writing general purpose code in the Functional Programming style [1]. It's not the only language that supports this style, but it's one of the most opinionated about keeping to this style that is also general-purpose, pragmatic, and has some industry adoption [2]. You can also see read what wiki.haskell.org has to say [3].
[1] "Why Functional Programming Matters": https://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.p...
[2] Commercial Haskell: https://github.com/commercialhaskell/commercialhaskell#readm...
[3] "Why use Haskell": https://wiki.haskell.org/Introduction#Why_use_Haskell.3F
> If you're asking people to learn Haskell in order to find out which kinds of programs it's better on
I'm not asking people to do anything, but if they do want to understand the tradeoffs of any technology, sometimes the only way is the hard way: learning it. I find all too often what people really want to know is a quick and easy glance at how much language X differs from something they already know (usually C derivatives, or Java, or Javascript, or Python).
I don't think it's unreasonable to expect a more concrete reply to that quesiton than "First master the language, then figure it out."
I've learned Haskell and used it for a relatively long time until I finally understood what is so nice about it. Again, very hard to explain, and a lot of that comes just from the combination of simple, functional language features. Like: how currying works together with function composition; how sum-types and product-types make it easy to model your domain / problem and using pattern matching to write code that is easy to understand and does the right thing; how a powerful type-system can be leveraged to rule certain bugs out almost completely, right from the design phase. Leveraging monads by using Haskell's special `do` syntax.
I only really understood this after having done imperative style programming, then having done functional style programming, and then trying to apply the functional style in an imperative environment and seeing why it does not work there (typically because of some missing language feature).
Edit: Just wanted to point out, I am not a fan of Haskell as a whole, since there are a lot of drawbacks in my opinion. There are valuable things to learn from the language, but I do think Rust is superior.
Let me be honest here and say I don't find your tone helpful. "You still haven't told us" makes you sound as if you're in a group, critiquing from the tribune. This isn't helpful for honest conversations. There's no "us", there's just you, and I don't owe you any explanation.
That said, I provided plenty of links in my answer above, which address at least some of your questions. Have you read them? The site https://www.haskell.org has plenty of testimonials that you could also read to figure why some shops and people have chosen Haskell.
Maybe you could send Simon Peyton Jones an email, he's one of the friendliest guys in the software industry. I don't think I've ever read or heard him say anything dismissive about any other person or technology.
What I cannot do: provide you with a single sentence stating why you should use Haskell. I don't think anyone can. For the record, I found your single sentence about Rust totally unconvincing as well; I do find Rust compelling because of tutorials, long articles I read about it, and a workshop I once did with a Rust practitioner. None of this is equivalent to debating/convincing on HN.
(Similarly, I find Go not compelling because I had to use it for my day job and everything about it made me chafe).
So my advice to you: read the links I provided, and keep in mind they are just a starting point. Do a workshop. Work on a midsize problem, maybe also write some Advent of Code Haskell solutions.
Or not. It's ok to just go with your gut feeling and focus on Rust. There's a finite amount of time you have available for exploring technologies. Rust will serve you well.
The links you gave provide general information about Haskell, but do not answer that question, from what I can see. I don't want a single sentence reason, just a compelling one.
Again: I'm not doing this to be adversarial. A decent number of people seem to really love Haskell and extol its virtues. So I'm trying to carefully check that I'm not missing something.
Haskell is a general purpose language, so it's good for any domain well served by a general purpose language. The rest is the list of benefits of statically typed, lazy first, pure functional programming languages.
"Haskell or Rust?" is not a question that can be meaningfully and objectively answered in a comment on HN.
And the rest of the answer is, essentially, "beyond that, if you want to see, you're going to have to learn it". I also don't find that unreasonable - there's only so much you can explain to someone who doesn't know the language. And that's not just Haskell, that's any language. I kind of have an idea of what Rust is about, but if I want to really understand it, I'm going to have to learn it. Same with Haskell, or Lisp, or pretty much anything.
So I found the_af's answer to be quite helpful. And I'm the guy who asked the question, so...
I agree: If the problem is "How do I get paid?" and the best available job requires learning Haskell, then learn Haskell!
But, I think this is kind of an evasive answer. First, not many jobs require Haskell, so if my choice of language is dictated by economic concerns I'm better off with, say, Python or various web dev stacks. Second, because I have in mind a situation in which the implementer has a fixed problem and is trying to figure out which language to use. (A personal project, say.) I'm sorry if this was not clear.
So, I ask again: are there any problems for which Haskell is a better solution than Rust?
edit: Regarding the Ruby question, I think the language has various flaws, but going into detail would take way too time. A shorter answer is: numpy, scipy, pytorch, numba.
Well, and what have you found so far in relation to Rust and Haskell? It seems to me you know what you have to do.
Let's assume your answer is "I read every introductory page in wiki.haskell.org, read and worked through a couple of tutorials, and I still cannot figure it out". If so, do you think a comment here in HN is going to convince you of picking language X over Y?
> So, I ask again: are there any problems for which Haskell is a better solution than Rust?
Realistically, which kind of answer do you expect? A summary of the "Why Haskell" and "Why Rust" pages? I'm sure they exist and you could take a look at them and decide.
Yes. Because I'm a highly fallible person and very open to the idea that a Haskell expert might be able to point out a good use case that I missed.
> Realistically, which kind of answer do you expect? A summary of the "Why Haskell" and "Why Rust" pages? I'm sure they exist and you could take a look at them and decide.
The selling point of Rust is (very, very) roughly "C++ without the bad parts, and some more good parts." Given the demonstrated utility of C++ (and demonstrated pitfalls) this is manifestly appealing. Avoiding memory safety related security holes alone is huge.
That's an example of the kind of answer I expect.
I'm not a Haskell expert, I just dabbled with it and liked it.
> The selling point of Rust is (very, very) roughly "C++ without the bad parts, and some more good parts." Given the demonstrated utility of C++ (and demonstrated pitfalls) this is manifestly appealing. Avoiding memory safety related security holes alone is huge.
The selling point of Haskell is that it's a Functional Programming first language (see: "Why Functional Programming Matters"), has a better statically type system than C/C++/Java which makes whole classes of bugs common in those languages harder to write in Haskell (so if writing correct code is a priority, that's your use case), and memory safety related security holes are harder to write, just like with Rust. Laziness (or non-strictness, whatever) is also a big if controversial selling point (why: read "Why Functional Programming Matters").
If you like slightly less opinionated (or non-strict by default) languages, you could go with OCaml or Standard ML instead.
Why would you prefer Rust? Why don't you ask a Rust advocate?
A lot of this translates to Rust, as Haskell influenced the language design of Rust. In Rust you have `std::option::Option` and `std::result::Result` which relate closely to `Maybe` and `Either`, respectively. Also pattern matching is available in Rust.
When you then look at other (imperative) languages like Go, C, and C++, error handling becomes a bit more cumbersome IMHO. I am not talking about explicit or implicit error handling. It's more about urging the programming to check for and handle errors, and also giving them the necessary tools to do that efficiently.
In Go, you have lots of `if err != nil { return err }`, which is cumbersome to write (luckily we have snippets) and _clutters_ the code. Yes, it is explicit and easy to read, but I don't think error handling should make up 4/5 of the lines of your algorithm.
The same applies to C, more or less, as functions typically tell you about success or failure via their return value. Like `err` in Go.
In C++ we have `std::optional` which is handy, but C++ lacks a lot of functional features and convenient syntax to take full advantage of it. No straight forward pattern matching here. There is `std::variant` to create sum types, but I've only seen that in use occasionally. There is also `std::expected` on the horizon, which is similar to `Either` / `std::result::Result`, but adoption will take ages.
C++, being a complicated language, makes it very difficult to just come up with your own wrapper classes that _just work_. See https://github.com/oktal/result/blob/master/result.h for example.
data Void where
Void :: { absurd :: forall a. a } -> Void
^ I just defined a type with no inhabitants [1] along with the ability to use a value of it to prove anything. And it leans on the type system features & ergonomics Go & Rust don't even get close to having.This is a pedantic example in a way, but this type is actually very useful in practice! And defining the type almost reads like English (or at least math English.)
Haskell is just a different world. You program with type variables of different shapes and sizes and relationships like it's nothing and it Just Works. Go's new generics & Rust's are crufty in comparison. Both due to syntax and semantics.
[1] modulo bottom..I know, I know :)
Since GHC 9.2, with UnliftedDatatypes you can define real uninhabited types!
{-# LANGUAGE UnliftedDatatypes #-}
import GHC.Exts
data Void :: TYPE UnliftedRep where
Void :: { absurd :: forall a. a } -> Void"I'm running Ubuntu so I installed ghc and cabal-install, then installed stack (since people are recommending that) by running their script. Then I found out that haskell-platform is the blessed route (and contains stack) so I uninstalled ghc, cabal, stack and installed that instead. Stack was not installed along with haskell-platform (what? why? ugh... whatever), so I reinstalled it manually.
Great, now I have the tooling all set up! Slightly more irritating than other languages, but it's there.
Now to build my app; I want to give websockets a whirl so I grabbed the server example and stuck it in a newly created stack project (stack new foo worked well) as app/Main.lhs and re-pointed foo.cabal to look at the .lhs extension. Ok, next step is to build it, stack build - it complains that I don't have websockets installed, ok, stack install websockets - it whirrs away for a while downloading stuff and then finishes. That was easy. stack build - same error, still no websockets (???). I take a look through the stack.yml and foo.cabal files and can't find websockets mentioned anywhere (in NodeJS I'd have done npm install --save websockets and it would have both installed the lib local to the project and updated the packages.json file appropriately - same sort of thing with Python via pip + freeze). Presumably I missed the '--save' or equivalent, but I don't see anything like this in the stack install -h docs.
I hop onto irc for help, and am informed that you don't stack install project dependencies; that installs global packages (huh? I thought stack was supposed to help in keeping things local... whatever). Then I find that I have to edit the foo.cabal file manually to add my deps - seriously? Wow. Ok... So I do that (in the wrong place, then eventually in the right place) and finally my stack build works. Awesome! But also grrrr! Why are there two config files talking about libs and how am I supposed to know which one I'm meant to add stuff to?
As an aside there's also the expectation that I should figure out which versions of libs are snapshotted on stackage, but searching on the website funnels me through to hackage (via hoogle) and gives me no indication on the way as to what snapshots they have. I ended up finding the snapshot listings on stackage and using ctrl+f in the browser to figure that out - after checking my stack.yaml to work out what snapshot list I should be looking at. Seriously. These leaps are crazy :)"
I should point out this is from 5 years ago. Probably things are better now. But some things are not, e.g. installing Haskell on Arch Linux [1].
[0] https://www.reddit.com/r/haskell/comments/4sihcv/comment/d5a...
While I get not everyone has the same background, stack works very similarly to how C#, java, rust and just about every other compiled language with its own dependency management system works. His being surprised says more about him that it does stack.
Python, which you mentioned in your other comment, is super irritating re: tooling -- yet people seldom find the need to "justify" using it.
Sure, the simplest (and mostly wrong) way of setting Python up is seemingly trivial, just like Haskell's. You'll soon run into all kinds of trouble with pip and dependencies and environments and typechecking and linting and the myriad of confusing and slightly incompatible tools that form Python's wider ecosystem.
As I say though, I think things are moving in a better direction now (I haven't taken a look at Haskell for a while).
Today you would install 'ghcup', which manages compilers and build tools. Default installation includes the compiler (GHC) and build tool (cabal). Then you create a folder, run 'cabal init', add 'websockets' to your '.cabal' file ('build-depends'), and you're good to go (run 'cabal build/run'). I think it's pretty reasonable now, far better than other alternatives.
If in general... do you know about Jane Street? From Wikipedia:
> Jane Street [...] adopted OCaml as its main programming language early on because the language's functional programming style and clear expressiveness made it possible for code reviews to be performed by traders who were not programmers, to verify that high-performance code would do what it was intended to do. [...] "OCaml helps us to quickly adapt to changing market conditions, and go from prototypes to production systems with less effort"
Doesn't seem like either research or fooling around to me! Those sound like actual, pragmatic, business-related benefits!
I don't think I'm exactly alone, but there's definitely lots of people that would disagree.
I know about Jane Street and I admire they manage to do so, but I also think lots of security issues occur because the language/system/library/framework in use is not well understood and Ocaml makes that particularly hard in my opinion. And I'm not talking about the "functional programming is hard" problem, because I don't find it harder than other paradigms I tried. I'm talking about the quality of the docs and the speed with which the language evolves.
> [OCaml's] clear expressiveness made it possible for code reviews to be performed [at Jane Street] by traders who were not programmers
If OCaml was a mess, difficult to understand, or had terrible docs, what the quote describes just wouldn't be possible. Non-programmers doing code reviews! What could be more pragmatic than that?
Do you have a citation for this? I'd love to read more.
Every interaction is processed by a Haskell rule engine to check for spam.
Facebook uses btrfs in production and I'm sure it works great for them, but that doesn't mean btrfs is a good fs.
And Jane Street has basically built their own stdlib for Ocaml, didn't they?
be specific
And that's fine, we need research languages and I'll gladly continue to write software in Ocaml, but I wouldn't want to pick it for a project I'd want to be well engineered.