Learning Haskell has been made much easier with Haskell Book[1]. Unlike LYAH, it actually has a ton of exercises and in-depth explanations so you understand the why behind things as you make progress. That said, it requires discipline to read through.
The big problem I've had with Haskell is that even after gaining a pretty good understanding of the language (including monads and such) I still can't fathom how to do anything real with it.
Exercises are great and all, but once I try to go past exercises, I start getting lost in layers of monad transformers, and I struggle to figure out the "right" way to do anything. It just feels like there are all these layers of abstraction and complexity that are required for even simple applications, and I can't seem to reach the point where it all clicks for me and becomes manageable.
Reading the TOC and chapter notes for that book, I'm not convinced it'll help me. Even the "final project" at the end of the book is described as "a little weird, but small". I don't need more weird, small examples, I need a full-fledged application! I've tried picking out random Haskell OSS apps and studying them, but without newbie-friendly documentation to walk me through the code, I find it very hard to follow what's happening....
I'd recommend just making yourself pick up a project, and run with it. Try not to over think it, and if you start to feel paralyzed, just say "fuck it, I'll do it the first, shittiest way that comes to mind."
As an example, the first "real" project I wrote in Haskell was one or two weeks into learning it: a web testing framework/DSL (a la Capybara[0]) that spoke a (custom) protocol over socket to a headless webkit instance[1].
Looking back, I abused stuff like type-classes and such, but then again, it was all a learning experience. I should probably be a little embarrassed about how I left the project, but in the interest of providing some inspiration, here it is in all its gory -- I mean, glory: https://github.com/cstrahan/happybara
I completely agree with the "write shit code" approach. That's how I learn any new language. As long as you adopt an attitude where you are aware that you're writing bad code and are willing to adapt and learn better processes as you progress, then it's the quickest way to getting proficient. Much like that immersion technique of learning a foreign language by moving to another language.
Yeah, the key is to start out writing shit code, but to skim over and get a feel for when you might use the more advanced concepts so that when the time comes that you think you might be able to apply something you know what to look for quickly.
> I'd recommend just making yourself pick up a project, and run with it. Try not to over think it, and if you start to feel paralyzed, just say "fuck it, I'll do it the first, shittiest way that comes to mind."
I tried that. When I got stuck (fairly early on), I ended up switching my project from Haskell to Clojure :/
Try doing everything in IO, passing stuff around by hand and ignoring all that abstraction.
You will immediately spot some places where a monad will help you. Where that happens, use the monad, elsewhere, keep it simple. With time you will regret some of that simple code, when that happens, change it (Haskell's best use case is on refactoring). With even more time you'll get a taste for where it's good to go complex from the start.
> I still can't fathom how to do anything real with it
That's incredibly easy, of your list of "problems to attack and programs to write some time soon" pick any one and get busy. It'll feel real-world very soon and there's no better way to grasp "real-world Haskell". The first iteration will be ugly, but on the plus side you'll notice that yourself and that's quite some progress already. Keep at it a bit more and perceived "decent post-newb proficiency" is within reach. Well-rounded mature libraries for "real-world periphery" (DBs, json/yaml/html/xml/all that jazz) abound, too.
What I find much more annoying is the lack of freelance projects. It's literally the language of academics, hobbyists, weekenders, late-nighters, githubbers. (Certainly also suitable for bootstrappers imho in a "Viaweb-Lisp-advantage" kinda way) If you want to avoid full-time employ, you're gonna have to keep doing .net/java/golang/node and such projects. Haskell code-bases I feel are private well-guarded silos within academia and a number of corps, no wider "projects ecosystem" to speak of.
> The big problem I've had with Haskell is that even after gaining a pretty good understanding of the language (including monads and such) I still can't fathom how to do anything real with it
I agree with you but the book has chapters where you write a URL shortener and the final project is an implementation of the `finger` Unix command. For me, the book was a stepping stone towards materials like Write You a Scheme (Scheme interpreter in Haskell).
I will admit though, I read Haskell Book for the ideas and learning typed functional programming. I wasn't planning on using Haskell everyday for projects.
I second this. Learning less popular languages, you drive off a cliff when you get to the intermediate stage. I wasted a lot of time because I didn't which language extensions (developed over last the 20 years but never added to the base language) and modules are generally seen as essential. Books and web tutorials didn't talk much about them, but the real world was different. I was like I was thrown out the tutorial-door into a wide world of questionable documentation and implicit knowledge known only by wizards in IRC, if ye dare idle to find 'em.
If you use a good "IDE" setup, it'll tell you what extensions you should enable for some code to compile. Intero (on Emacs) allows you to hit C-c C-r to insert the relevant incantation at the top of the file.
About what extensions people consider kosher, Stephen Diehl's "What I Wish I Knew When Learning Haskell" has a great list that sorts them into "common", "uhh", and "you obviously know what you're doing".
Fwiw I have been writing production Haskell for years, am comfortable with Category Theory etc, and most of my code is still in "records and pure functions (that act on records)" style.
You don't have to use the most esoteric constructs the language offers, or get into the weeds of how lenses work (just a random example of a seemingly 'esoteric' library) or language extensions to write code that does something useful.
That said, a project centred Haskell book would be nice to have.
Servant allows you to write a type that describes a server/API, and automatically derives a specification for it. You can then write handlers for the different API endpoints, and it will only compile if every endpoint is correctly handled. That includes content types, status codes, and so on, everything is verified, and things are often derived for you. All (de)serialization to/from JSON is automatic (although you can write your own instances if you want your JSON to look a certain way).
For example, from the Servant docs:
type API = "position" :> Capture "x" Int :> Capture "y" Int :> Get '[JSON] Position
:<|> "hello" :> QueryParam "name" String :> Get '[JSON] HelloMessage
:<|> "marketing" :> ReqBody '[JSON] ClientInfo :> Post '[JSON] Email
This is equivalent to an API that defines these three endpoints:
GET /position/:x/:y/ returns a Position object as JSON
GET /hello?name=whatever returns a HelloMessage object as JSON
POST /marketing given a JSON request that represents a ClientInfo object,
returns an Email object as JSON
but the spec is code: code that the compiler can check for you!
You can then write functions of the following types
handlePosition :: Int -> Int -> Handler Position
handleHello :: Maybe String -> Handler HelloMessage
handleMarketing :: ClientInfo -> Handler Email
where "Handler thing" effectively means that you can do something like write to a log or throw an exception while you return the thing. This will typecheck, and you have a server that must do what it says on the "tin", the tin being the API type above.
If you add a new API endpoint, and forget to write a Handler for it, you'll get to know.
If you change the Position type to work with x, y, and z coordinates but forget to update your handlers, you'll get to know.
If you'd like to also allow clients to request HTML instead for some endpoint, just change the '[JSON] to '[JSON,HTML]. The Haskell typesystem will make sure that someone requesting a text/html Content-Type doesn't get hit with a 500 or something.
Note the Maybe String there: if you wrote a handler for the /hello endpoint that had the type String -> Handler HelloMessage, Servant would complain: you're expecting a query parameter, which the client doesn't have to provide. This is in stark contrast to, say, the "NoneType has no attribute whatever" problems that one risks having to face with Django: if it compiles, it meets the spec.
Of course, static typing won't prevent you from responding to /hello with Lovecraft quotes.
--
> I start getting lost in layers of monad transformers
Handler is actually a monad transformer, and it's a great first one: it's essentially[0]
type Handler a = ExceptT ServantErr (ReaderT Config IO) a
if memory serves, which means that a "Handler a" is a computation that can
* throw a ServantErr
* read values from a Config object
* perform IO actions (read files, make other network requests, log things, "fire missiles")
when run, returning a value of type a. Anecdotally, monad transformers never clicked for me until I started muddling through actually using them in code like this.
After a couple of months, you realise it's not too wrong to say you understand how to use them, and you slowly begin to be able to rely on the type system for support. Libraries like Servant are a great example of how this can really, really help. I stopped to think last week how similar it is to pair-programming with a really intelligent but sometimes obtuse friend who likes pointing out how "this doesn't follow from your assumptions", all the way from
> "Wait, but you can't add two books together."
to
> "What if someone PUTs to /login?"
which is what we had above, to
> "And what happens if I try to withdraw all my money exactly when the payment I've made to you is getting executed?"
(in this case, you discover the wonders of software transactional memory[1]). A better typesystem allows you to let the compiler handle more of the busywork that you'd originally have written tests or comments for.
It is sometimes confusing starting out (when one discovers that 3 isn't an Int, but a "Num a => a", for instance), but it gets better. Once you get past the Project Euler/"look ma, infinite lists!" stuff, "real" Haskell does have a tendency to make people underestimate how much they really know, but as I've discovered, taking the plunge reveals that one has progressed much farther than one thinks.
Also, #haskell on Freenode is one of the friendliest places I've encountered on the internet[0].
Corrode is a C-to-Rust converter written in literate Haskell (as in, it's like a blog post that you can compile and run, to give a slightly strained analogy).
I wrote a 3D mesh reconstruction algorithm using feature point extraction in Haskell. The hardest part was graph algorithms since those can be pretty tricky to express in functional languages. But Even with 3D output to OpenGL, image loading and manipulation, etc.. I never touched a monad transformer. I think you are trying too hard. Just embrace IO for the effects and move everything else to pure code.
This document describes an algorithm for validating an XML document against a RELAX NG schema. This algorithm is based on the idea of what's called a derivative (sometimes called a residual). It is not the only possible algorithm for RELAX NG validation. This document does not describe any algorithms for transforming a RELAX NG schema into simplified form, nor for determining whether a RELAX NG schema is correct.
We use Haskell to describe the algorithm. Do not worry if you don't know Haskell; we use only a tiny subset which should be easily understandable.
That was similar to my thinking. I chuckled a bit when I saw so much of what I think folks would consider corporate tool-sets like VBA being used in the day compared to like Haskell (that I've never seen in the professional world but know several people that hack around in it) being written at night. Kind of a fun chart.
I'm torn between laughing and crying; having used VBA extensively in the past.
I've used VBA for stupid things like Excel based apps (not stupid at the time, but in hindsight there was a better way) and stupid things like HMI software with VBA hooks (GE Fanuc Cimplicity, in case you were wondering).
I don't think that's accurate. Microsoft has a role in the development and maintenance of Haskell because they currently employ Simon P. Jones, one of the big driving forces behind Haskell, as a researcher.
However, new versions of Haskell (the language) are created by temporary committees (which are not composed by Microsoft).
GHC (the main implementation) is an open source project with developers from different organizations. According to this page (https://ghc.haskell.org/trac/ghc/wiki/TeamGHC), SPJ is the only one employed by Microsoft. He is one of the core contributors and he owns a large part of the code base, but not to such an extent that GHC can be called a Microsoft project even if Microsoft would want that. Haskell is not a MS product, it has been under development since well before SPJ was employed by MS.
Finally, I'm not aware of MS funding the project beyond paying SPJ's wage.
They're not focusing on Haskell commercially, but in Microsoft Research where they employ some of the main Haskell devs. A lot of their research has gone into F#, C# and .NET libraries (like LINQ).
One of the biggest(.) Google projects with Haskell is probably Ganeti ( https://github.com/ganeti/ganeti ), which is a mix of python and Haskell and has been around since 2008ish (although Haskell was introduced later, iirc).
We recently moved our main development to github so the repo seems a bit empty, we're certainly happy to get more contributors if you are interested, as the community is fairly small and specialized. Everyone is welcome.
Source: I'm one of the current main developers of the project.
(.) Note: I actually have no idea if it's the 'biggest'.
A huge chunk of the site integrity bits (e.g. general spam prevention and application of this technology to other problem spaces like instant messages, etc.) for Facebook are done in Haskell and if you know Haskell and fancy working in London I am fairly certain that team is always on the lookout for new people.
Yes, please note that BigTechCo using something in production is not an endorsement that it's production-ready. Ironically, more often than not, it means the opposite. BigTechCo employs the best computer scientists in the world to make all of that stuff work together, frequently including the project's founders/BDFLs so they can get whatever changes they need rammed through. Your company does not have this luxury.
I used to feel that way. I tried reading the various tutorial-style learning materials online, such as Learn You a Haskell, but they didn’t really help me learn how to use the language. In the end, I just dove in and started trying to build real software with it, asking questions when I got stuck. Even though there was a lot to learn, it turned out to be pretty easy.
Nowadays Haskell is my #1 programming language for hobby projects—at least when GC is acceptable. And often when I’m trying to design some code in another language, I’ll prototype it in Haskell first to get more clarity of thought and faster iteration.
Hehe, those have both been on my to-do-one-day-this-time-for-sure-list for quite a while.
I remember Lisp having a fixed place on that list (pun intended?) for a number of years, copious amount of caffeine, weed, and patience eventually allowed me to grok it. Haskell has been more stubborn in that regard. I get the functional part just fine, but the part where you get side effects and I/O and such confuses me to no end. Maybe I should just give up on Haskell finally and try OCaml, which seems to offer many of the same benefits.
Except in his 5th chart (the animated one), all the enterprise technologies and Haskell all pulsed up in the morning and afternoon local time, while Haskell was the only one to also pulse up in the evening. In fact, Haskell's evening pulse was smaller than its daytime pulse.