In Haskell you can get most work done without the advanced concepts, but you can always choose to dig into the meaty stuff and get even more leverage from the type system. Easy to start, hard to master, keeps things very interesting for a a very long time. By the time you think you've mastered most of what it has to offer, the next version of GHC comes out with new goodies, now you can learn even more superpowers.
Btw, the title says "when", not "before", big difference.
I find articles like this pretty useful and always bookmark them. They are useful for me when I've already invested the time to learn the rudimentary basics of a language; after that, each of these tips usually provides an 'a-ha' moment and saves me from learning something the hard way...but I wouldn't start reading this before getting yourself to at least an elementary understanding of the material.
The title should really be "Stuff that I wish I had quick reference material for when learning Haskell". You might need a few of those sections for specific application areas (and that's how they are organized), but you can safely ignore the rest.
syntax. of the dozen languages i've taught myself, (which is a super-set of the half dozen i've used to write significant things), Haskell's syntax has been, and remains, the largest barrier for me (and this includes perl!). For example, just a clear equivalence, like this one given by the very helpful linked article here, would've helped enormously ("sugared form" for monad):
do { a <- f ; m } ≡ f >>= \a -> do { m }
Sometimes i think the authors of Haskell had a completely different glyph set. I'm sure some of you folks can read this like a book, but this sort of thing still throws me into the ditch:
M2 :: (Monad m) => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
It takes a while to master reading math notation or music notation. Mastering reading Haskell isn't that different. Some people are served well enough by just learning guitar tabs, others feel they're better off mastering music notation.
IMO there are many nice things about Haskell, but simplicity is not one of them. It's very consciously a "big" language, rather than a "small" one. As others have mentioned, you can declare your own operators with custom precedence. And don't forget the whitespace rules either. Lennart Augustsson, implementor of at least one Haskell compiler, has said this at some point:
Implementing exactly Haskell's rule for indentation is incredibly hard. In fact, no known Haskell compiler gets it right.
For the record, I can read both standard notation music and guitar tabs. I'm fairly competent at Haskell have written APL/J/K derivative languages for a living. "Mastering reading Haskell" certainly has to do with a lack of "go to this page on the wiki/hoogle/haddock and you can read the meaning and idiomatic usage of the 95% most common operators", not a lack of conceptual grasp of anything difficult.
The Haskell notation is a simple, concise representation of the actual semantics. If you try to transpose those semantics to a more conventional notation intended for different semantics, it gets complicated due to the mismatch.
This notation I’ve suggested doesn’t even accurately express such details as currying and typeclasses, which the original notation conveys neatly.
1. It's way longer
2. Naming the monad "Action" may be misleading depending
on choice of Monad
3. It's tied syntactically to the syntax of the implementation
4. The <>s are superfluous
5. The argument names are superfluous (to the type)
6. The explicit type quantification is superfluous and verbose
Because of the much longer type names which have nothing to do with the syntax.
By just replacing all the type names by the original single-letter names, it goes from 107 to 72 characters, that's almost 50% increase in size (49%) due to longer type names, which incidentally is nearly double the increase in size between the Haskell signature and this new signature (57 -> 72, or 26%)
Funnily enough, this expansion is relatively worse if applied to the Haskell signature (57 -> 87, +53%)
> Naming the monad "Action" may be misleading depending on choice of Monad
Nothing to do with syntax either.
> It's tied syntactically to the syntax of the implementation
?
> The argument names are superfluous (to the type)
That can trivially be removed when just displaying the function's type (`f`'s arguments are not explicitly named after all), likewise for the unnecessary type quantifications, so a type-view of this function (rather than a source view) could be:
Conventions are as important as syntax when it comes to legibility of a language, so phrasing “M” as “Action” seemed a fair comparison. And if you want to be true to the semantics, you might write something like this:
> Sometimes i think the authors of Haskell had a completely different glyph set.
Well, its an ML-derived syntax rather than the more common Algol-derived syntax, which forms something of a familiarity obstacle for programmers whose background is largely in Algol-derived syntaxes.
Its probably somewhat easier if you've learned another ML family language first -- especially given that idiomatic Haskell often involves wrapping your head around semantics that are unfamiliar as well, so that you aren't trying to take on both at once.
OTOH, I think the kind of ML-based syntax Haskell uses is a good fit, and its worth learning.
It's funny you should ask this, because you're right that some types really are quite hard to read and there was a great discussion a few days ago where someone mentioned that the types tell you a lot about what the function is doing, and then someone retorted that most examples of types guiding you are usually very simple, and posted a really complex type for people to decipher, and the more proficient Haskellers actually worked it out--based partly on their previous knowledge of similar types! See http://www.reddit.com/r/haskell/comments/3ijtej/any_tips_for...
Now, I'm not at that level of proficiency, but I can tell that your example above takes a binary function and 'lifts' it into a higher (monadic) context, so that it can work on monadic values. And the reason I can work this out is because I know about the Functor typeclass which has the function fmap :: (a -> b) -> f a -> f b, which does a similar job of lifting an input function into a higher context (in this case a functor context).
But ... but ... Haskell has the least syntax of any "mainstream" language (save LISP, without macros).
Your example of course is `do` notation which is tricky, and is really kind of advanced -- it's much better to use `>>=` `>>` and `return` as long as you can stand before breaking out `do`. If nothing else avoiding `do` will make you write smaller functions!
By "syntax" of course I mean "keywords". Haskell allows for infix operator creativity which you might see as a drawback. I would rather have a language be maximally expressive, allow me to define my own infix swear-word "operators", than be coddled and censored like almost every other language outside C++. But as for built-in syntax, there's hardly any. `$` and `.` are freaking library functions.
As for types, well, types are hard to read. Why shouldn't they be? It's not like templates are easy in C++ once you leave the most trivial exercises. At least Haskell's are formally consistent and fundamentally related to your definitions -- unlike templates which are really macro soup.
In any case, I would find your `M2` definition a lot easier to read with `a` and `b` instead of `a1` and `a2` ...
What I still do not know and always wished to know when I learned Haskell was how to write efficient code easily. I wrote huge projects with thousands of lines knowing nothing about C++ execution model and had insanely fast code (that could have been made even faster - but I was not that kind of expert) but with Haskell I have to be an expert to really write code that is as performant as something that would take me much less time to write in C/C++.
Just writing simple efficient matrix multiplication is a pain. It took me a couple of days to write a working quicksort.
I couldn't find any resources that provide a very serious introduction to optimizing Haskell code.
I found out way too late in my adventures with Haskell that Monad Transformers and similar abstractions have a significant runtime overhead and aren't free, I thought I was just playing with types that won't get in the way when the code compiles.
Don't do something that generates thunks in a long-running loop which'll hold references to them. (This applies to JS...virtually any language with GC and first-class functions as well). This is pretty easy to fix and identify once you know what you're doing.
Don't use String. Use Text for Text, ByteString for raw bytes.
Related to String: don't use lists for large datasets unless you're intentionally modeling and reasoning about your data as an infinite space. Use Vector if it's finite, fits in memory, and you're going to comprehend it all at once. Vector gives you cache-friendliness as well.
As a safe default: lazy in the spine, strict in the leaves.
Use streaming libraries (Pipes, Conduit) for processing large datasets. I did a test with a csv parsing library and compared the non-streaming (default) interface and the streaming interface provided by pipes-csv for summing columns in a ~6mb CSV.
No streaming used 30mb of heap.
Naive streaming used 10mb.
Pipes used 600kb.
monad-control and mtl (monad transformer libraries) are pretty fast and can be used without much (any?) worry in 99.999% of circumstances.
Use attoparsec and be mindful of backtracking anytime you're doing perf sensitive parsing. If you hit a limit, you may need to use a parser generator but this is almost never the case. If you need to parse something huge...use a streaming parser.
Sometimes CPS transformation can be a huge boon. Read what Bryan O'Sullivan was written about this for the parsing side of it. Kmett has good examples of CPS transformation for performance in his libraries as well.
Use async.
Default to using TVars (STM containers) for correctness until you know what specific properties you need. If you get perf sensitive but still want transactions, turn the scope of your transactions into cells of a data structure. Cf. http://hackage.haskell.org/package/stm-containers when you have composable concurrency abstractions, it can become just yet another data structures problem.
If you're writing a (very) hot loop, you'll probably end up looking to avoid boxing (just like Java) and touching the heap (just like Java, C, C++). Don Stewart has written good, thorough examples of this.
Resources:
Anything Don Stewart has ever written
Kmett's libraries and blog
Bryan O'Sullivan's libraries (particularly attoparsec and aeson) and blog
Johan Tibell is the strictness perf honcho. Check his libraries for ideas if you're making something strict. Don Stewart has written along these lines too.
My own book http://haskellbook.com/ will explain how to reason about performance and laziness, though it's primarily a practical beginner's book. Focus WRT perf will be more on understanding the foundations, how things evaluate, how the runtime works so you can absorb all the other information as easily as possible.
Koalafications:
Every backend I work on in ad tech, including the public facing adserver, is written in Haskell. Our adserver latencies range 12-17ms with some pretty gentle 99th percentiles. The average DSP we talk to has response times in the low hundreds (100-400).
I am a freelance computer programmer from India. I have been teaching Haskell myself for the past 3-4 months. I have stopped for a while, because I am hard pressed to find a job where I can work remotely. Can you look at some code I have written and let me know if I can put Haskell as something I can put in my resume? If yes, what is the best way to put it.
Here is the code.
1. A simple neural network with back propogation algorithm that recognizes alphabets letters on a 8x8 grid.
What are my chances of getting a remote Haskell job? Based on my experience, What kind of position/pay can I expect to get? If it matters, I have 9 years of professional experience in developing web applications.
I don't really have time to do a proper code review, but here are some thoughts from glancing.
It's petty, but the visual appearance of your code will affect how a client evaluates your knowledge of Haskell. You could use stylish-haskell and hindent to help clean things up.
We use a (tiny) Pipes project to tech screen candidates because it's usually stuff like Pipes/Conduit that'll make somebody thrash - not straight-forward stuff in IO. Ability to overcome or preexisting experience is what we're looking for. That doesn't necessarily apply to other companies hiring/contracting with Haskellers of course.
I don't know what your focus is, but Haskell isn't _too_ much different from other PLs in that a lot of the work is web, so I'd recommend getting comfortable in Yesod & Snap. Nothing wrong with Spock/Scotty, but a lot of apps will be written in them. There is more numerical work to be had, but if you just want to get work that is Haskell, whatever that may be, that's where you'll want to get comfy.
The projects you've linked look non-trivial and pretty cool, just needs refinement that comes from experience and improvement. Beyond that, seek out sticking points that trip up beginning/intermediate Haskell programmers like getting comfortable in mature web frameworks, with monad transformers, and with a streaming library or two. (Pipes and Conduit)
I'd recommend contributing to an existing library as well, if you have the time.
I can't guarantee you'll find a Haskell gig if you do all this. If you're serious about finding one, your best bets are consulting with one that already uses Haskell (start keeping a spreadsheet of companies using Haskell and whom you've contacted) or join an early ...
Bought your book a while ago -- didn't realize your background was in ad tech. I personally eeked out ~30ms avg latencies with PHP by modifying ReactPHP (non-blocking event loop) and getting creative with Redis and nginx.
It's performing comparably at high loads, and saving us a ton of money but obviously... it's PHP. I'm obsessed with Haskell and have spent a bit of time playing around with HLearn as I think SVM is an obvious use case where it would excel (though in terseness/structure more than performance relative to C).
Any advice on selling a rewrite and/or challenges as one nears 1B daily queries for which Haskell would be uniquely advantageous?
I want to integrate Haskell in our high-frequency serving arm (or as a backup, for machine learning), but honestly don't know enough about it relative to performance to sell its advantages over Erlang, Go or even C. Aside from the obvious "functional is better" and "types are great," which tend to appeal to the folks who see beauty in the language, is it feasible to claim that Haskell will result in a faster, more performance program in less time? ... And not to wear out my welcome, but I'm interested in reading more about performant Haskell (as per your post); any resources you recommend?
This is my second ad-tech gig but I'm more of a catch-all SSE that is into databases/dist-sys and who usually works at startups.
>I personally eeked out ~30ms avg latencies with PHP by modifying ReactPHP
That's quite good. We haven't done any real tuning or cleanup with our application, I think if we did we could get a fair bit lower. The fact is, our app is fast because we avoid network I/O like the plague and we don't write _totally_ clownshoes Haskell code. It hasn't taken much work otherwise. We even have unnecessary String/List values, inefficient parsers, and some other things rolling around. Haven't had time for a clean sweep (feature push rn).
>Any advice on selling a rewrite and/or challenges as one nears 1B daily queries for which Haskell would be uniquely advantageous?
Haskell's just really good at anything enterprise really. Frontend JS, API, traditional web backend. As long as you avoid weird/unpleasant libraries and you're proficient/comfortable in Haskell it can be a great experience. Libraries in Haskell are generally pretty opinionated so you need to make sure you know what you like. HLearn is a good example of that opinionatedness being very fecund but also unusual to people accustomed to more ordinary ML libraries. HLearn is super cool :)
Haskell's a bit less compelling for non-JS apps because you'll be serving a volleyball over the FFI net (iOS, Android) but I know people that have done both fruitfully and happily. Haskell for Mac (http://haskellformac.com/) is a Swift+Haskell app from what I understand from Chakravarty. Manuel Chakravarty's done some really cool work on enabling programmers to avoid FFI (not that it's bad, the FFI is really quite nice actually) through the use of the inline objective c support.
> honestly don't know enough about it relative to performance to sell its advantages over Erlang, Go or even C.
If you have the labor, time, and money to write something in C, I want to work where you work.
So that I can write it in Haskell and use the spare time to make it extra shiny.
Okay I'll take the Erlang/Go bits seriously:
Erlang: if you're perf sensitive, shared memory is reaaaaallyyyy nice. The concurrency primitives in Haskell give you database-style transactions which COMPOSE, you can't do that in Erlang. Re: shared memory - look at how much of CouchDB was C. Haskell has a superset of the options Erlang offers. It doesn't excel as deeply in the niche Erlang offers but I think it does a credible job.
Go: Okay, Go has shared memory but Haskell again has a superset of options. The most common concurrency primitives in Haskell are the TVar (I default to this one for correctness) and the MVar. The Tvar is your STM container - that's where your transactions come from. MVar is a bit like a Golang channel in that it blocks by default unlike Erlang's messaging.
However, we can get away with defaulting to having blocking APIs because our threading is _cheaper_ than Erlang's! Green threads + shared memory -> fuck it, fire off a thread. It's also nice because it means we can preserve our usual synchronous intuition within the context of a single thread and block when we really do want to block.
We actually have an even smaller and cheaper execution context called a spark, but that's more concerned with parallelism than concurrency so we'll put it aside for the moment.
My desire to be productive is at odds with my appreciation for Haskell. Don't get me wrong, I love the language, it's elegant, absolutely awesome (apart from whitespaces with semantic meaning). But sometimes I feel like the language, despite its expressiveness, is like a tight straitjacket. And then I just write some JavaScript or Java or C++ or PHP and feel so much freer.
I like to think of Haskell's types as traffic lights. They might get in the way if you're the only driver on the road but the moment you have to deal with other people they are a life saver.
That's why people favor Haskell in enterprise environments because types keep everything sane when you have multiple people working on the same project or you have large third-party dependency trees.
pandoc, shellcheck and xmonad.
is this still the list of things you can install that were written in haskell that are used for something that isn't writing haskell code?
What I wish I knew now that I know Haskell: Where I can find Haskell jobs that aren't in banking! I have grown a love of the language through using it, but I don't know how to find many job positions that aren't either in banking or research.
My understanding is that it's the expressiveness and the type safety along with being functional and immutable (by default) in order to ensure correct programs are being written (which is obviously a concern when lots of money is moving about.)
What I wish I knew now that I know Haskell: Where I can find Haskell jobs that aren't in banking! I have grown a love of the language through using it, but I don't know how to find many job positions that aren't either in banking or research.
The author covers cabal sandbox, which I used until recently when I converted my few Haskell projects to use stack. I was really happy with stack until a few days ago when I tried to add some old Haskell code to a new yesod web app. Dependency hell that took a while to sort out.
This article discussed getting everything working and then doing a cabal freeze which is something I hadn't seen before. I would like to be able to simply update a project to new library versions but maybe I should drop that desire. Any advice?
I'm not sure cabal can really be considered a package manager as the article here states [1]. Stack helps, but I think just using a dedicated package manager to manage haskell things is probably the way to go.
Nix has a lot of haskell packages in it already, and guix has a hackage 'import' tool which helps you with writing a new package definition for a project that hasn't already been packaged.
You may think that's overkill, and fair enough. But I've been through cabal hell before, and I'd honestly rather not anymore, ever.
I wish I hadn't bothered learning Haskell. I spent years thinking I was an idiot because I struggled and failed to make any even moderately complex programs. Now I'm using C++ and things are so much easier. I think leaving Haskell feels like leaving an abusive partner who always puts you down.
63 comments
[ 4.9 ms ] story [ 650 ms ] threadhttps://new-hn.algolia.com/?experimental&sort=byDate&prefix&...
Btw, the title says "when", not "before", big difference.
It's in no way comparable to learning math notation or music notation.
There's a few things, like fixity declarations, that make parsing Haskell not quite as easy as it could be.
Implementing exactly Haskell's rule for indentation is incredibly hard. In fact, no known Haskell compiler gets it right.
https://mail.haskell.org/pipermail/haskell-cafe/2009-April/0...
For the record, I can read both standard notation music and guitar tabs. I'm fairly competent at Haskell have written APL/J/K derivative languages for a living. "Mastering reading Haskell" certainly has to do with a lack of "go to this page on the wiki/hoogle/haddock and you can read the meaning and idiomatic usage of the 95% most common operators", not a lack of conceptual grasp of anything difficult.
This notation I’ve suggested doesn’t even accurately express such details as currying and typeclasses, which the original notation conveys neatly.
Because of the much longer type names which have nothing to do with the syntax.
By just replacing all the type names by the original single-letter names, it goes from 107 to 72 characters, that's almost 50% increase in size (49%) due to longer type names, which incidentally is nearly double the increase in size between the Haskell signature and this new signature (57 -> 72, or 26%)
Funnily enough, this expansion is relatively worse if applied to the Haskell signature (57 -> 87, +53%)> Naming the monad "Action" may be misleading depending on choice of Monad
Nothing to do with syntax either.
> It's tied syntactically to the syntax of the implementation
?
> The argument names are superfluous (to the type)
That can trivially be removed when just displaying the function's type (`f`'s arguments are not explicitly named after all), likewise for the unnecessary type quantifications, so a type-view of this function (rather than a source view) could be:
Oh look, it's now shorter than the original signature (though somewhat more noisy, I'll give you that)But the conventions are whatever we want for a resyntacting no?
> However, concision is not the goal
I was answering a comment putting concision forward as reasons to dislike the alternate syntax.
Clearly, as you demonstrate, the syntax described can be shortened—but it wasn't.
And by the definition being tied to the implementation I mean that it's not possible to write, e.g.
pekk asked what was wrong with the syntax.
> Clearly, as you demonstrate, the syntax described can be shortened—but it wasn't.
I didn't change the syntax in any way.
> And by the definition being tied to the implementation I mean that it's not possible to write, e.g.
'k.
Is that actually used? Global type inference I could see, but that seems odder.
It is used quite frequently, actually, e.g. in describing type classes.
Well, its an ML-derived syntax rather than the more common Algol-derived syntax, which forms something of a familiarity obstacle for programmers whose background is largely in Algol-derived syntaxes.
Its probably somewhat easier if you've learned another ML family language first -- especially given that idiomatic Haskell often involves wrapping your head around semantics that are unfamiliar as well, so that you aren't trying to take on both at once.
OTOH, I think the kind of ML-based syntax Haskell uses is a good fit, and its worth learning.
Now, I'm not at that level of proficiency, but I can tell that your example above takes a binary function and 'lifts' it into a higher (monadic) context, so that it can work on monadic values. And the reason I can work this out is because I know about the Functor typeclass which has the function fmap :: (a -> b) -> f a -> f b, which does a similar job of lifting an input function into a higher context (in this case a functor context).
Your example of course is `do` notation which is tricky, and is really kind of advanced -- it's much better to use `>>=` `>>` and `return` as long as you can stand before breaking out `do`. If nothing else avoiding `do` will make you write smaller functions!
By "syntax" of course I mean "keywords". Haskell allows for infix operator creativity which you might see as a drawback. I would rather have a language be maximally expressive, allow me to define my own infix swear-word "operators", than be coddled and censored like almost every other language outside C++. But as for built-in syntax, there's hardly any. `$` and `.` are freaking library functions.
As for types, well, types are hard to read. Why shouldn't they be? It's not like templates are easy in C++ once you leave the most trivial exercises. At least Haskell's are formally consistent and fundamentally related to your definitions -- unlike templates which are really macro soup.
In any case, I would find your `M2` definition a lot easier to read with `a` and `b` instead of `a1` and `a2` ...
Just writing simple efficient matrix multiplication is a pain. It took me a couple of days to write a working quicksort.
I couldn't find any resources that provide a very serious introduction to optimizing Haskell code.
I found out way too late in my adventures with Haskell that Monad Transformers and similar abstractions have a significant runtime overhead and aren't free, I thought I was just playing with types that won't get in the way when the code compiles.
No one seems to cover this aspect of Haskell.
Don't use String. Use Text for Text, ByteString for raw bytes.
Related to String: don't use lists for large datasets unless you're intentionally modeling and reasoning about your data as an infinite space. Use Vector if it's finite, fits in memory, and you're going to comprehend it all at once. Vector gives you cache-friendliness as well.
As a safe default: lazy in the spine, strict in the leaves.
Use streaming libraries (Pipes, Conduit) for processing large datasets. I did a test with a csv parsing library and compared the non-streaming (default) interface and the streaming interface provided by pipes-csv for summing columns in a ~6mb CSV.
No streaming used 30mb of heap.
Naive streaming used 10mb.
Pipes used 600kb.
monad-control and mtl (monad transformer libraries) are pretty fast and can be used without much (any?) worry in 99.999% of circumstances.
Use attoparsec and be mindful of backtracking anytime you're doing perf sensitive parsing. If you hit a limit, you may need to use a parser generator but this is almost never the case. If you need to parse something huge...use a streaming parser.
Sometimes CPS transformation can be a huge boon. Read what Bryan O'Sullivan was written about this for the parsing side of it. Kmett has good examples of CPS transformation for performance in his libraries as well.
Use async.
Default to using TVars (STM containers) for correctness until you know what specific properties you need. If you get perf sensitive but still want transactions, turn the scope of your transactions into cells of a data structure. Cf. http://hackage.haskell.org/package/stm-containers when you have composable concurrency abstractions, it can become just yet another data structures problem.
If you're writing a (very) hot loop, you'll probably end up looking to avoid boxing (just like Java) and touching the heap (just like Java, C, C++). Don Stewart has written good, thorough examples of this.
Resources:
Anything Don Stewart has ever written
Kmett's libraries and blog
Bryan O'Sullivan's libraries (particularly attoparsec and aeson) and blog
Johan Tibell is the strictness perf honcho. Check his libraries for ideas if you're making something strict. Don Stewart has written along these lines too.
http://book.realworldhaskell.org/ is out of date but the stuff on perf and debugging are some of the best in the book.
My own book http://haskellbook.com/ will explain how to reason about performance and laziness, though it's primarily a practical beginner's book. Focus WRT perf will be more on understanding the foundations, how things evaluate, how the runtime works so you can absorb all the other information as easily as possible.
Koalafications:
Every backend I work on in ad tech, including the public facing adserver, is written in Haskell. Our adserver latencies range 12-17ms with some pretty gentle 99th percentiles. The average DSP we talk to has response times in the low hundreds (100-400).
Mostly the stuff touching libraries will break but if you know where to look on Hackage you can fix it.
[0] http://stackoverflow.com/a/23733494/1651941
I am a freelance computer programmer from India. I have been teaching Haskell myself for the past 3-4 months. I have stopped for a while, because I am hard pressed to find a job where I can work remotely. Can you look at some code I have written and let me know if I can put Haskell as something I can put in my resume? If yes, what is the best way to put it.
Here is the code.
1. A simple neural network with back propogation algorithm that recognizes alphabets letters on a 8x8 grid.
https://bitbucket.org/sras/haskell-stuff/src/default/snn.hs?...
2. A port (partial) of my side project web application in PHP/MySQL to Haskell using Spock framework.
https://bitbucket.org/sras/babloos-hs/src/06bffa288865af1fc3...
What are my chances of getting a remote Haskell job? Based on my experience, What kind of position/pay can I expect to get? If it matters, I have 9 years of professional experience in developing web applications.
It's petty, but the visual appearance of your code will affect how a client evaluates your knowledge of Haskell. You could use stylish-haskell and hindent to help clean things up.
We use a (tiny) Pipes project to tech screen candidates because it's usually stuff like Pipes/Conduit that'll make somebody thrash - not straight-forward stuff in IO. Ability to overcome or preexisting experience is what we're looking for. That doesn't necessarily apply to other companies hiring/contracting with Haskellers of course.
I don't know what your focus is, but Haskell isn't _too_ much different from other PLs in that a lot of the work is web, so I'd recommend getting comfortable in Yesod & Snap. Nothing wrong with Spock/Scotty, but a lot of apps will be written in them. There is more numerical work to be had, but if you just want to get work that is Haskell, whatever that may be, that's where you'll want to get comfy.
https://bitbucket.org/sras/babloos-hs/src/06bffa288865af1fc3... looks Maybe Monad'ish.
https://bitbucket.org/sras/babloos-hs/src/06bffa288865af1fc3... you can kill duplication like this by having a getOne variant of your query function. Many db clients provide this.
https://bitbucket.org/sras/babloos-hs/src/06bffa288865af1fc3... this is what I mean by petty cleanup.
https://bitbucket.org/sras/babloos-hs/src/06bffa288865af1fc3... Use a quasiquoter so you can write the query naturally, but inline in the code.
https://bitbucket.org/sras/babloos-hs/src/06bffa288865af1fc3... this whole datatype is kinda suspect and you need newtypes for the Text soup. See Bloodhound below for how I use newtypes to make the types more useful.
If you'd like example code, my Elasticsearch client is pretty reasonable I think: https://github.com/bitemyapp/bloodhound
The projects you've linked look non-trivial and pretty cool, just needs refinement that comes from experience and improvement. Beyond that, seek out sticking points that trip up beginning/intermediate Haskell programmers like getting comfortable in mature web frameworks, with monad transformers, and with a streaming library or two. (Pipes and Conduit)
I'd recommend contributing to an existing library as well, if you have the time.
I can't guarantee you'll find a Haskell gig if you do all this. If you're serious about finding one, your best bets are consulting with one that already uses Haskell (start keeping a spreadsheet of companies using Haskell and whom you've contacted) or join an early ...
Bought your book a while ago -- didn't realize your background was in ad tech. I personally eeked out ~30ms avg latencies with PHP by modifying ReactPHP (non-blocking event loop) and getting creative with Redis and nginx.
It's performing comparably at high loads, and saving us a ton of money but obviously... it's PHP. I'm obsessed with Haskell and have spent a bit of time playing around with HLearn as I think SVM is an obvious use case where it would excel (though in terseness/structure more than performance relative to C).
Any advice on selling a rewrite and/or challenges as one nears 1B daily queries for which Haskell would be uniquely advantageous?
I want to integrate Haskell in our high-frequency serving arm (or as a backup, for machine learning), but honestly don't know enough about it relative to performance to sell its advantages over Erlang, Go or even C. Aside from the obvious "functional is better" and "types are great," which tend to appeal to the folks who see beauty in the language, is it feasible to claim that Haskell will result in a faster, more performance program in less time? ... And not to wear out my welcome, but I'm interested in reading more about performant Haskell (as per your post); any resources you recommend?
hand wobble
This is my second ad-tech gig but I'm more of a catch-all SSE that is into databases/dist-sys and who usually works at startups.
>I personally eeked out ~30ms avg latencies with PHP by modifying ReactPHP
That's quite good. We haven't done any real tuning or cleanup with our application, I think if we did we could get a fair bit lower. The fact is, our app is fast because we avoid network I/O like the plague and we don't write _totally_ clownshoes Haskell code. It hasn't taken much work otherwise. We even have unnecessary String/List values, inefficient parsers, and some other things rolling around. Haven't had time for a clean sweep (feature push rn).
>Any advice on selling a rewrite and/or challenges as one nears 1B daily queries for which Haskell would be uniquely advantageous?
Haskell's just really good at anything enterprise really. Frontend JS, API, traditional web backend. As long as you avoid weird/unpleasant libraries and you're proficient/comfortable in Haskell it can be a great experience. Libraries in Haskell are generally pretty opinionated so you need to make sure you know what you like. HLearn is a good example of that opinionatedness being very fecund but also unusual to people accustomed to more ordinary ML libraries. HLearn is super cool :)
Haskell's a bit less compelling for non-JS apps because you'll be serving a volleyball over the FFI net (iOS, Android) but I know people that have done both fruitfully and happily. Haskell for Mac (http://haskellformac.com/) is a Swift+Haskell app from what I understand from Chakravarty. Manuel Chakravarty's done some really cool work on enabling programmers to avoid FFI (not that it's bad, the FFI is really quite nice actually) through the use of the inline objective c support.
> honestly don't know enough about it relative to performance to sell its advantages over Erlang, Go or even C.
If you have the labor, time, and money to write something in C, I want to work where you work.
So that I can write it in Haskell and use the spare time to make it extra shiny.
Okay I'll take the Erlang/Go bits seriously:
Erlang: if you're perf sensitive, shared memory is reaaaaallyyyy nice. The concurrency primitives in Haskell give you database-style transactions which COMPOSE, you can't do that in Erlang. Re: shared memory - look at how much of CouchDB was C. Haskell has a superset of the options Erlang offers. It doesn't excel as deeply in the niche Erlang offers but I think it does a credible job.
Worth considering re: Erlang:
1. http://hackage.haskell.org/package/courier
2. http://haskell-distributed.github.io/
Go: Okay, Go has shared memory but Haskell again has a superset of options. The most common concurrency primitives in Haskell are the TVar (I default to this one for correctness) and the MVar. The Tvar is your STM container - that's where your transactions come from. MVar is a bit like a Golang channel in that it blocks by default unlike Erlang's messaging.
However, we can get away with defaulting to having blocking APIs because our threading is _cheaper_ than Erlang's! Green threads + shared memory -> fuck it, fire off a thread. It's also nice because it means we can preserve our usual synchronous intuition within the context of a single thread and block when we really do want to block.
We actually have an even smaller and cheaper execution context called a spark, but that's more concerned with parallelism than concurrency so we'll put it aside for the moment.
If you want a rundown on strengths & we...
That's why people favor Haskell in enterprise environments because types keep everything sane when you have multiple people working on the same project or you have large third-party dependency trees.
Haskell is an enterprise language, not an application language. The benefits of Haskell have played out better there.
Check out Servant while you're at it, it's awesome.
If you don't like writing the client-end in Javascript, you can use Haste or GHCJS and do it in Haskell.
WAI already supports HTTP/2.0 (before Apache has got around to it).
This article discussed getting everything working and then doing a cabal freeze which is something I hadn't seen before. I would like to be able to simply update a project to new library versions but maybe I should drop that desire. Any advice?
Nix has a lot of haskell packages in it already, and guix has a hackage 'import' tool which helps you with writing a new package definition for a project that hasn't already been packaged.
You may think that's overkill, and fair enough. But I've been through cabal hell before, and I'd honestly rather not anymore, ever.
[1]: https://ivanmiljenovic.wordpress.com/2010/03/15/repeat-after...
[0]https://www.stackage.org/