Which of Haskell and OCaml is more practical? For example, in which aspect will each play a key role? - Quora

11 weeks ago by nhaliday

- Tikhon Jelvis,

Haskell.

This is a question I'm particularly well-placed to answer because I've spent quite a bit of time with both Haskell and OCaml, seeing both in the real world (including working at Jane Street for a bit). I've also seen the languages in academic settings and know many people at startups using both languages. This gives me a good perspective on both languages, with a fairly similar amount of experience in the two (admittedly biased towards Haskell).

And so, based on my own experience rather than the languages' reputations, I can confidently say it's Haskell.

Parallelism and Concurrency

...

Libraries

...

Typeclasses vs Modules

...

In some sense, OCaml modules are better behaved and founded on a sounder theory than Haskell typeclasses, which have some serious drawbacks. However, the fact that typeclasses can be reliably inferred whereas modules have to be explicitly used all the time more than makes up for this. Moreover, extensions to the typeclass system enable much of the power provided by OCaml modules.

...

Of course, OCaml has some advantages of its own as well. It has a performance profile that's much easier to predict. The module system is awesome and often missed in Haskell. Polymorphic variants can be very useful for neatly representing certain situations, and don't have an obvious Haskell analog.

While both languages have a reasonable C FFI, OCaml's seems a bit simpler. It's hard for me to say this with any certainty because I've only used the OCaml FFI myself, but it was quite easy to use—a hard bar for Haskell's to clear. One really nice use of modules in OCaml is to pass around values directly from C as abstract types, which can help avoid extra marshalling/unmarshalling; that seemed very nice in OCaml.

However, overall, I still think Haskell is the more practical choice. Apart from the reasoning above, I simply have my own observations: my Haskell code tends to be clearer, simpler and shorter than my OCaml code. I'm also more productive in Haskell. Part of this is certainly a matter of having more Haskell experience, but the delta is limited especially as I'm working at my third OCaml company. (Of course, the first two were just internships.)

Both Haskell and OCaml are uniquivocally superb options—miles ahead of any other languages I know. While I do prefer Haskell, I'd choose either one in a pinch.

--

I've looked at F# a bit, but it feels like it makes too many tradeoffs to be on .NET. You lose the module system, which is probably OCaml's best feature, in return for an unfortunate, nominally typed OOP layer.

I'm also not invested in .NET at all: if anything, I'd prefer to avoid it in favor of simplicity. I exclusively use Linux and, from the outside, Mono doesn't look as good as it could be. I'm also far more likely to interoperate with a C library than a .NET library.

If I had some additional reason to use .NET, I'd definitely go for F#, but right now I don't.

https://www.reddit.com/r/haskell/comments/3huexy/what_are_haskellers_critiques_of_f_and_ocaml/

https://www.reddit.com/r/haskell/comments/3huexy/what_are_haskellers_critiques_of_f_and_ocaml/cub5mmb/

Thinking about it now, it boils down to a single word: expressiveness. When I'm writing OCaml, I feel more constrained than when I'm writing Haskell. And that's important: unlike so many others, what first attracted me to Haskell was expressiveness, not safety. It's easier for me to write code that looks how I want it to look in Haskell. The upper bound on code quality is higher.

...

Perhaps it all boils down to OCaml and its community feeling more "worse is better" than Haskell, something I highly disfavor.

...

Laziness or, more strictly, non-strictness is big. A controversial start, perhaps, but I stand by it. Unlike some, I do not see non-strictness as a design mistake but as a leap in abstraction. Perhaps a leap before its time, but a leap nonetheless. Haskell lets me program without constantly keeping the code's order in my head. Sure, it's not perfect and sometimes performance issues jar the illusion, but they are the exception not the norm. Coming from imperative languages where order is omnipresent (I can't even imagine not thinking about execution order as I write an imperative program!) it's incredibly liberating, even accounting for the weird issues and jinks I'd never see in a strict language.

This is what I imagine life felt like with the first garbage collectors: they may have been slow and awkward, the abstraction might have leaked here and there, but, for all that, it was an incredible advance. You didn't have to constantly think about memory allocation any more. It took a lot of effort to get where we are now and garbage collectors still aren't perfect and don't fit everywhere, but it's hard to imagine the world without them. Non-strictness feels like it has the same potential, without anywhere near the work garbage collection saw put into it.

...

The other big thing that stands out are typeclasses. OCaml might catch up on this front with implicit modules or it might not (Scala implicits are, by many reports, awkward at best—ask Edward Kmett about it, not me) but, as it stands, not having them is a major shortcoming. Not having inference is a bigger deal than it seems: it makes all sorts of idioms we take for granted in Haskell awkward in OCaml which means that people simply don't use them. Haskell's typeclasses, for all their shortcomings (some of which I find rather annoying), are incredibly expressive.

In Haskell, it's trivial to create your own numeric type and operators work as expected. In OCaml, while you can write code that's polymorphic over numeric types, people simply don't. Why not? Because you'd have to explicitly convert your literals and because you'd have to explicitly open a module with your operators—good luck using multiple numeric types in a single block of code! This means that everyone uses the default types: (63/31-bit) ints and doubles. If that doesn't scream "worse is better", I don't know what does.

...

There's more. Haskell's effect management, brought up elsewhere in this thread, is a big boon. It makes changing things more comfortable and makes informal reasoning much easier. Haskell is the only language where I consistently leave code I visit better than I found it. Even if I hadn't worked on the project in years. My Haskell code has better longevity than my OCaml code, much less other languages.

http://blog.ezyang.com/2011/02/ocaml-gotchas/

One observation about purity and randomness: I think one of the things people frequently find annoying in Haskell is the fact that randomness involves mutation of state, and thus be wrapped in a monad. This makes building probabilistic data structures a little clunkier, since you can no longer expose pure interfaces. OCaml is not pure, and as such you can query the random number generator whenever you want.

However, I think Haskell may get the last laugh in certain circumstances. In particular, if you are using a random number generator in order to generate random test cases for your code, you need to be able to reproduce a particular set of random tests. Usually, this is done by providing a seed which you can then feed back to the testing script, for deterministic behavior. But because OCaml's random number generator manipulates global state, it's very easy to accidentally break determinism by asking for a random number for something unrelated. You can work around it by manually bracketing the global state, but explicitly handling the randomness state means providing determinism is much more natural.

q-n-a
qra
programming
pls
engineering
nitty-gritty
pragmatic
functional
haskell
ocaml-sml
dotnet
types
arrows
cost-benefit
tradeoffs
concurrency
libraries
performance
expert-experience
composition-decomposition
comparison
critique
multi
reddit
social
discussion
techtariat
reflection
review
random
data-structures
numerics
rand-approx
sublinear
syntax
volo-avolo
causation
scala
jvm
ecosystem
metal-to-virtual
Haskell.

This is a question I'm particularly well-placed to answer because I've spent quite a bit of time with both Haskell and OCaml, seeing both in the real world (including working at Jane Street for a bit). I've also seen the languages in academic settings and know many people at startups using both languages. This gives me a good perspective on both languages, with a fairly similar amount of experience in the two (admittedly biased towards Haskell).

And so, based on my own experience rather than the languages' reputations, I can confidently say it's Haskell.

Parallelism and Concurrency

...

Libraries

...

Typeclasses vs Modules

...

In some sense, OCaml modules are better behaved and founded on a sounder theory than Haskell typeclasses, which have some serious drawbacks. However, the fact that typeclasses can be reliably inferred whereas modules have to be explicitly used all the time more than makes up for this. Moreover, extensions to the typeclass system enable much of the power provided by OCaml modules.

...

Of course, OCaml has some advantages of its own as well. It has a performance profile that's much easier to predict. The module system is awesome and often missed in Haskell. Polymorphic variants can be very useful for neatly representing certain situations, and don't have an obvious Haskell analog.

While both languages have a reasonable C FFI, OCaml's seems a bit simpler. It's hard for me to say this with any certainty because I've only used the OCaml FFI myself, but it was quite easy to use—a hard bar for Haskell's to clear. One really nice use of modules in OCaml is to pass around values directly from C as abstract types, which can help avoid extra marshalling/unmarshalling; that seemed very nice in OCaml.

However, overall, I still think Haskell is the more practical choice. Apart from the reasoning above, I simply have my own observations: my Haskell code tends to be clearer, simpler and shorter than my OCaml code. I'm also more productive in Haskell. Part of this is certainly a matter of having more Haskell experience, but the delta is limited especially as I'm working at my third OCaml company. (Of course, the first two were just internships.)

Both Haskell and OCaml are uniquivocally superb options—miles ahead of any other languages I know. While I do prefer Haskell, I'd choose either one in a pinch.

--

I've looked at F# a bit, but it feels like it makes too many tradeoffs to be on .NET. You lose the module system, which is probably OCaml's best feature, in return for an unfortunate, nominally typed OOP layer.

I'm also not invested in .NET at all: if anything, I'd prefer to avoid it in favor of simplicity. I exclusively use Linux and, from the outside, Mono doesn't look as good as it could be. I'm also far more likely to interoperate with a C library than a .NET library.

If I had some additional reason to use .NET, I'd definitely go for F#, but right now I don't.

https://www.reddit.com/r/haskell/comments/3huexy/what_are_haskellers_critiques_of_f_and_ocaml/

https://www.reddit.com/r/haskell/comments/3huexy/what_are_haskellers_critiques_of_f_and_ocaml/cub5mmb/

Thinking about it now, it boils down to a single word: expressiveness. When I'm writing OCaml, I feel more constrained than when I'm writing Haskell. And that's important: unlike so many others, what first attracted me to Haskell was expressiveness, not safety. It's easier for me to write code that looks how I want it to look in Haskell. The upper bound on code quality is higher.

...

Perhaps it all boils down to OCaml and its community feeling more "worse is better" than Haskell, something I highly disfavor.

...

Laziness or, more strictly, non-strictness is big. A controversial start, perhaps, but I stand by it. Unlike some, I do not see non-strictness as a design mistake but as a leap in abstraction. Perhaps a leap before its time, but a leap nonetheless. Haskell lets me program without constantly keeping the code's order in my head. Sure, it's not perfect and sometimes performance issues jar the illusion, but they are the exception not the norm. Coming from imperative languages where order is omnipresent (I can't even imagine not thinking about execution order as I write an imperative program!) it's incredibly liberating, even accounting for the weird issues and jinks I'd never see in a strict language.

This is what I imagine life felt like with the first garbage collectors: they may have been slow and awkward, the abstraction might have leaked here and there, but, for all that, it was an incredible advance. You didn't have to constantly think about memory allocation any more. It took a lot of effort to get where we are now and garbage collectors still aren't perfect and don't fit everywhere, but it's hard to imagine the world without them. Non-strictness feels like it has the same potential, without anywhere near the work garbage collection saw put into it.

...

The other big thing that stands out are typeclasses. OCaml might catch up on this front with implicit modules or it might not (Scala implicits are, by many reports, awkward at best—ask Edward Kmett about it, not me) but, as it stands, not having them is a major shortcoming. Not having inference is a bigger deal than it seems: it makes all sorts of idioms we take for granted in Haskell awkward in OCaml which means that people simply don't use them. Haskell's typeclasses, for all their shortcomings (some of which I find rather annoying), are incredibly expressive.

In Haskell, it's trivial to create your own numeric type and operators work as expected. In OCaml, while you can write code that's polymorphic over numeric types, people simply don't. Why not? Because you'd have to explicitly convert your literals and because you'd have to explicitly open a module with your operators—good luck using multiple numeric types in a single block of code! This means that everyone uses the default types: (63/31-bit) ints and doubles. If that doesn't scream "worse is better", I don't know what does.

...

There's more. Haskell's effect management, brought up elsewhere in this thread, is a big boon. It makes changing things more comfortable and makes informal reasoning much easier. Haskell is the only language where I consistently leave code I visit better than I found it. Even if I hadn't worked on the project in years. My Haskell code has better longevity than my OCaml code, much less other languages.

http://blog.ezyang.com/2011/02/ocaml-gotchas/

One observation about purity and randomness: I think one of the things people frequently find annoying in Haskell is the fact that randomness involves mutation of state, and thus be wrapped in a monad. This makes building probabilistic data structures a little clunkier, since you can no longer expose pure interfaces. OCaml is not pure, and as such you can query the random number generator whenever you want.

However, I think Haskell may get the last laugh in certain circumstances. In particular, if you are using a random number generator in order to generate random test cases for your code, you need to be able to reproduce a particular set of random tests. Usually, this is done by providing a seed which you can then feed back to the testing script, for deterministic behavior. But because OCaml's random number generator manipulates global state, it's very easy to accidentally break determinism by asking for a random number for something unrelated. You can work around it by manually bracketing the global state, but explicitly handling the randomness state means providing determinism is much more natural.

11 weeks ago by nhaliday

mg.metric geometry - What is the best way to peel fruit? - MathOverflow

q-n-a overflow nibble math acm sublinear metrics metric-space proofs math.CO tcstariat arrows reduction measure math.MG similarity multi papers survey computational-geometry cs algorithms pdf positivity msr tidbits intersection curvature convexity-curvature intersection-connectedness signum

february 2017 by nhaliday

q-n-a overflow nibble math acm sublinear metrics metric-space proofs math.CO tcstariat arrows reduction measure math.MG similarity multi papers survey computational-geometry cs algorithms pdf positivity msr tidbits intersection curvature convexity-curvature intersection-connectedness signum

february 2017 by nhaliday

inequalities - Is the Jaccard distance a distance? - MathOverflow

february 2017 by nhaliday

Steinhaus Transform

the referenced survey: http://kenclarkson.org/nn_survey/p.pdf

It's known that this transformation produces a metric from a metric. Now if you take as the base metric D the symmetric difference between two sets, what you end up with is the Jaccard distance (which actually is known by many other names as well).

q-n-a
overflow
nibble
math
acm
sublinear
metrics
metric-space
proofs
math.CO
tcstariat
arrows
reduction
measure
math.MG
similarity
multi
papers
survey
computational-geometry
cs
algorithms
pdf
positivity
msr
tidbits
intersection
curvature
convexity-curvature
intersection-connectedness
signum
the referenced survey: http://kenclarkson.org/nn_survey/p.pdf

It's known that this transformation produces a metric from a metric. Now if you take as the base metric D the symmetric difference between two sets, what you end up with is the Jaccard distance (which actually is known by many other names as well).

february 2017 by nhaliday

MinHash - Wikipedia

february 2017 by nhaliday

- goal: compute Jaccard coefficient J(A, B) = |A∩B| / |A∪B| in sublinear space

- idea: pick random injective hash function h, define h_min(S) = argmin_{x in S} h(x), and note that Pr[h_min(A) = h_min(B)] = J(A, B)

- reduce variance w/ Chernoff bound

algorithms
data-structures
sublinear
hashing
wiki
reference
random
tcs
nibble
measure
metric-space
metrics
similarity
PAC
intersection
intersection-connectedness
- idea: pick random injective hash function h, define h_min(S) = argmin_{x in S} h(x), and note that Pr[h_min(A) = h_min(B)] = J(A, B)

- reduce variance w/ Chernoff bound

february 2017 by nhaliday

Count–min sketch - Wikipedia

february 2017 by nhaliday

- estimates frequency vector (f_i)

- idea:

d = O(log 1/δ) hash functions h_j: [n] -> [w] (w = O(1/ε))

d*w counters a[r, c]

for each event i, increment counters a[1, h_1(i)], a[2, h_2(i)], ..., a[d, h_d(i)]

estimate for f_i is min_j a[j, h_j(i)]

- never underestimates but upward-biased

- pf: Markov to get constant probability of success, then exponential decrease with repetition

lecture notes: http://theory.stanford.edu/~tim/s15/l/l2.pdf

- note this can work w/ negative updates. just use median instead of min. pf still uses markov on the absolute value of error.

algorithms
data-structures
sublinear
hashing
wiki
reference
bias-variance
approximation
random
tcs
multi
stanford
lecture-notes
pdf
tim-roughgarden
nibble
pigeonhole-markov
PAC
- idea:

d = O(log 1/δ) hash functions h_j: [n] -> [w] (w = O(1/ε))

d*w counters a[r, c]

for each event i, increment counters a[1, h_1(i)], a[2, h_2(i)], ..., a[d, h_d(i)]

estimate for f_i is min_j a[j, h_j(i)]

- never underestimates but upward-biased

- pf: Markov to get constant probability of success, then exponential decrease with repetition

lecture notes: http://theory.stanford.edu/~tim/s15/l/l2.pdf

- note this can work w/ negative updates. just use median instead of min. pf still uses markov on the absolute value of error.

february 2017 by nhaliday

Harvard CS 229r: Information Theory in Computer Science (Spring 2016)

course harvard information-theory tcs yoga 👳 topics bits madhu-sudan entropy-like motivation communication-complexity lower-bounds mihai algorithms data-structures sublinear space-complexity unit binomial p:* quixotic advanced

october 2016 by nhaliday

course harvard information-theory tcs yoga 👳 topics bits madhu-sudan entropy-like motivation communication-complexity lower-bounds mihai algorithms data-structures sublinear space-complexity unit binomial p:* quixotic advanced

october 2016 by nhaliday

Communication Complexity (for Algorithm Designers) (CS369E), Winter 2015

sublinear course stanford algorithms lower-bounds complexity tcs yoga 👳 lecture-notes topics communication-complexity tim-roughgarden space-complexity sparsity norms data-structures algorithmic-econ game-theory unit compressed-sensing p:someday quixotic advanced

september 2016 by nhaliday

sublinear course stanford algorithms lower-bounds complexity tcs yoga 👳 lecture-notes topics communication-complexity tim-roughgarden space-complexity sparsity norms data-structures algorithmic-econ game-theory unit compressed-sensing p:someday quixotic advanced

september 2016 by nhaliday

6.854/18.415 Advanced Algorithms, Spring 2016

course mit algorithms tcs yoga 👳 unit toolkit metabuch ankur-moitra init hashing sublinear graphs graph-theory linear-programming duality submodular gradient-descent iterative-methods online-learning ensembles SDP rounding random-networks latent-variables random-matrices average-case perturbation lecture-notes p:*** quixotic advanced optimization dimensionality embedding

july 2016 by nhaliday

course mit algorithms tcs yoga 👳 unit toolkit metabuch ankur-moitra init hashing sublinear graphs graph-theory linear-programming duality submodular gradient-descent iterative-methods online-learning ensembles SDP rounding random-networks latent-variables random-matrices average-case perturbation lecture-notes p:*** quixotic advanced optimization dimensionality embedding

july 2016 by nhaliday

The Modern Algorithmic Toolbox (CS168), Spring 2015-2016

course tcs yoga stanford algorithms synthesis 👳 mihai lecture-notes tim-roughgarden valiant unit hashing sublinear dimensionality embeddings norms gradient-descent toolkit metabuch regularization linear-algebra spectral sampling concentration-of-measure markov monte-carlo fourier sparsity linear-programming optimization expanders compressed-sensing high-dimension p:*** curvature matrix-factorization convexity-curvature quixotic elegance advanced embedding generalization exploratory differential-privacy

june 2016 by nhaliday

course tcs yoga stanford algorithms synthesis 👳 mihai lecture-notes tim-roughgarden valiant unit hashing sublinear dimensionality embeddings norms gradient-descent toolkit metabuch regularization linear-algebra spectral sampling concentration-of-measure markov monte-carlo fourier sparsity linear-programming optimization expanders compressed-sensing high-dimension p:*** curvature matrix-factorization convexity-curvature quixotic elegance advanced embedding generalization exploratory differential-privacy

june 2016 by nhaliday

**related tags**

Copy this bookmark: