This is currently not the case. It's sometimes not avoidable at all. Compile times are a real concern right now. A GHC maintainer has even confessed to it being a very significant issue.
So since making GHC drastically more efficient is an enormous problem, maybe getting Stack/Cabal to download binary caches would be the best way to go forward.
There's a Nix build server that offers all of Stackage in binary form. That really takes a lot of pain away, at least if you're on a supported architecture (x86_64, I guess). But it's run by a volunteer individual, I think.
Of course, Debian and others have been packaging Haskell binaries forever, but I don't think most people want to deal with distribution packages for development.
I'm sure there are lots of discussions about this in other places... All I've found from my random googling is this post which is about binary sharing on the same computer:
I've never used the open-source variant, but caching of intermediate targets allowing for speedy incremental builds is a big theme.
In particular we avoid "academic" features of the language like functors and first class modules, because they obscure the flow of the code and are a headache for ordinary programmers to understand. I often get requests from people from the OCaml academic community asking if we have any available positions, and the answer has so far always been no.
If you're hiring OCaml programmers who can't understand (or learn to understand) functors, you're probably doing something wrong. Even using the stdlib Hashtbl requires an understanding of functors.
In OO land, they're just a way to ensure that an argument satisfies an interface, exposing certain public functions and properties — just like an object in Java has to implement the Comparable interface in order to be sorted in a collection.
There isn't anything exactly analogous in Java. Functor application can introduce new type definitions at compile time and enforce static type safety. You need this so that you can statically require that you can only take unions of sorted collections whose types came from the same ordering module applied to the same ordered set module.
I'm surprised to hear they're often eschewed.
Typeclasses which are ad hoc, specific, and typically defined on a per project basis, are much more debatable. If you have the concept of "rendering to the screen" and you have typeclass Renderable with a render method then this is really no better than just writing separate functions for each instance of the Renderable. This isn't genuinely generic programming, it's just symbol overloading.
(Are you talking about this library?
I don't actually see a Renderable class there anyway.)
Yes, there's no 'Renderable' typeclass but there are 'Primitive's. There are no laws that the 'Primitive' typeclass instances must obey but there are associated types that need to be satisfied. I tried to write this without a typeclass and I just couldn't get it to check, so I turned to TypeFamilies to encode the relation ship between types. I'd love to make it more idiomatic though!
[I'd love some feedback if you're so inclined](https://github.com/schell/renderable/blob/master/src/Data/Re...)
Haskell programmers do seem to prefer typeclasses that come equipped with some set of meaningful "laws" that help to reject "unreasonable" instances.
And even without that, they are very useful for data type conversions and the like.
I don't understand what you're saying. Are those applicants to Red Hat, or developers asking to contribute to libguestfs that you say no to.
Also, according to this, There are basically three main contributors, including you, so I fail to see how training would be an issue ...
C++ is the worst offender, though.
In fact, the mapping is absolutely obvious. Haskell slightly brain damages us by assuming that setMap would have to apply to all a->b functions, which can't be done because a and b need to be Ord.
Although apparently it _can_ be done in GHC 8. ish.
* stack is pretty solid at multi-package builds, save everything in one single git repo for easier snapshotting. See yesod for reference
* use stack with stackage LTS unless you have a really good reason not to
* TH is nice to avoid, but you also miss out on great libraries like Persistent. Seems reasonably hard to dodge that one if you're sold on the conveniences of the yesod ecosystem
* We've been overall pretty happy with classy-prelude as Prelude replacement. Can throw off beginners at first, but is quite convenient to work with.
The part that most worried me was If we look at the history of programming, there are many portents of the future of Haskell in the C++ community, another language where no two developers (that I’ve met) agree on which subset of the language to use.
I also perked up when he talked about the difference between pipeline-paradigm coding and coding involving monadic trees.
I'd love to dive into the language, but with F# I'm happy enough that I code as little as possible and create lots of value. While I think that would be even more true in Haskell, it doesn't seem worth the switch -- yet.
Having said that, I'm definitely seeing some parallels between my own experience in F# and this author's experience in Haskell, especially the part about multiple ways to solve a problem. Are there no good books about common FP best practices? Seems like much of what you would consider a "best practice" would apply whether it's F#, OCAML, or Haskell.
I think the Haskell world would benefit from talking a bit more about "design patterns." I've seen the concept get a fair bit of abuse because of the claim that Haskell's abstraction facilities are good enough to eliminate the need for Visitor Pattern style boilerplate—which has truth to it, but loses the baby with the bathwater.
Design patterns as in "common ways to structure programs and parts of programs" are fundamental for people who are learning to program productively. They constitute the repertoire of coding on the level above syntax. They're the principal structures of the idiomatic lexicon. The good ones seem obvious once you understand them, but a poor grasp of them causes vague confusion and big missteps.
In Haskell (and pure FP in general), there are a lot of useful design patterns that beginners pick up from the ambient culture if they're lucky:
- the reader/state/IO monad transformer stack;
- domain values as algebraic structures e.g. monoids;
- functor composition;
- free monad interpreters;
- Xmonad-style pure core with I/O wrapper;
- explicit ID values for representing identity;
- recursion schemes;
- and so on and so on.
What I'm describing is far from a Haskell-specific problem, actually—there aren't that many resources in general that focus on these kinds of patterns.
When I was a beginner programmer, I was lucky to find Ward Cunningham's original wiki, the Portland Pattern Repository, which was all about spreading and discussing this kind of cultural conceptual knowledge.
There was a strong humanistic influence (from Christopher Alexander, through the early agile movement before it became a high-octane consultancy buzzword) and Haskell's culture has more DNA from mathematics and logic, and so treats patterns differently...
Still, I would love to see more discussion about functional patterns, at all scales from function implementation to application architecture.
Also, stuff like "strictness annotation" is not a function.
Ah but it should be :)
[Not a function actually, but a type constructor: http://h2.jaguarpaw.co.uk/posts/strictness-in-types/]
I think this happened to Ruby for some time, not anymore probably. Maybe the next language to get the benefits of the "experienced early adopters effect" will be Elixir.
I don't think you can beat other languages yet, except in some very niche areas. There's not even incremental compilation!
Hell, even python can infer function types these days!
Rust has been around much longer than Swift for example, and yet there are many very more production Swift apps. Whereas rust seems limited to play stuff.
Of course, given another 2-5 years it should catch up in many ways. Comparing it to mature languages, or languages like Swift (from the worlds largest company paying some of the worlds best language developers) is not really fair.
Definitely a play ground for enthusiasts at this point. Which I guess is what you meant.
Just because something says 1.0 doesn't mean it's usable :P
Conversion is part of the hassle, the other part is not having common functions (like, say, "splitPrefix") that will work across all string-like types.
For this, I recommend the monoid-subclasses package which, among other goodies, offers the TextualMonoid typeclass, that has instances for many string-like types.
I feel there must be some sort of story or interesting thing to learn here. Or is it just the usual str vs widestr type problems?
Also was interested to see the comment about huge records and the memory pressure it can cause. Seems like that's really an issue with immutability. I was expecting the author to provide some sort of advice or workaround for it, but apparently not.
The original Haskell strings were linked lists of characters. This was simple and elegant and worked well with the functional programming approach of the time (1980s, by the way, so maybe Haskell in its origins isn't quite so modern as you think). Nobody was much concerned about high performance string operations in Haskell at the time.
Inevitably, later people wanted to add more performant string types. But should they be lazy or strict? And do you want an abstract representation of Unicode, or do you want something more immediately suitable for arbitrary binary data? Enter four more string types. And now here we are with 5 string types in common use.
By "should the types be lazy or strict", you mean, if you do a string operation like uppercase/lowercase/substring/replace/etc, is that operation lazy or strict? Or are you meaning decoding bytes to characters or ... what aspect of the type itself can be lazy or strict?
I refactor huge parts of my code - can gut a particular API endpoint response and rewrite it without worrying about introducing more bugs. This allows me to start writing code without a lot of planning and refactor as I go instead of spending a lot of time upfront thinking through the implications.
Using Hoogle or Hayoo to search for functions based on types is just simply awesome. If you want a function that returns the index of a list that satisfies a predicate, you don't need to come up with search words instead you just look for it based on the types like so: http://hayoo.fh-wedel.de/?query=%28a+-%3E+Bool%29+-%3E+[a]+-.... This does not mean you can solve all problems this way but it is very quick to get easy answers than Googling or putting it on SO.
Most developers write their APIs and need to spend more time documenting it. With servant I just derive documentation directly from the types so my documentation moves in lock step with my code.
That said, using Haskell has its challenges (especially as a beginner).
* Compile-refresh cycle is frustrating. With Python or Go, you make a change and refresh the page, it is there. With Haskell, the 30s wait can become painful. My code is organized into modules but it is hard to avoid dependency related compile issues -- I tend to put most of my data records (mostly related by business logic) in a module and if you add anything to this module, you will end up recompiling everything that depends on it (which is most of the code). I am sure a pro-Haskeller would do it differently but whatever suggestions available online is not steering me in the right direction.
* Starting out with a fresh framework is not trivial for a beginner. servant is really nice because it came with very good documentation and also a tutorial by someone on how to use it with wai (http server) and persistent (an ORM). Without it, I would not have been able to get to where I am now.
* Not all libraries are created equal -- some of the common use cases are well documented or has enough documentation that you will be ok. But once you venture beyond common use cases, trying to use a library is not easy. Most of the time, types help and being able to test it in the REPL is nice but it can only take you so far. I recently looked at a library for creating a MIME string but got lost in some undocumented library.
* Haskell's community is great. You will always find someone to help you. However, as the author was saying, you want to get some work done and you cannot wait 2 days for an answer on Reddit or SO. IRC is great for specific libraries (say servant or Yesod) but general #haskell can be daunting -- 90% of the people seem to be discussing Lenses or Free Monads and your stupid type error is not going to get any attention.
* Easy parts of Haskell are very easy to pickup and the hard parts seem impossible to fully comprehend (I will think I understand Monad Transformers and will try to implement some logic but will get stuck in type check hell and quickly give up).
Btw, I did not know about fieldLabelModifier until now and it will cut down a lot of boiler plate. That said, I cannot wait for GHC 8 and its Duplicate Record Fields! Records are really annoying for writing business logic driven API servers.
The Haxl team seem to use this strategy:
"Haxl users at Facebook do a lot of development and testing inside GHCi. In fact, we’ve built a customized version of GHCi that runs code in our Haxl monad by default instead of the IO monad, and has a handful of extra commands to support common workflows needed by our developers."
In regards to changing data records I've suffered the same problem as well. At best I've isolated what I can into separate modules so the impact is smaller after a small change, but obviously isn't universally applicable.
Note that there is also a #haskell-beginners IRC channel where it's sometimes easier to get a responses to certain questions than the much broader #haskell channel. Both channels are full of incredibly nice people for sure.
I too did not know about fieldLabelModifier and am excited about the GHC 8 changes as well!
Generics is also not without its faults (it inflates compile time/memory, for example, see problems surrounding aeson 0.10). If the article is correct when it says that /[TH is] a eternal source of pain and sorrow/, then you're trading one pain for another.
For cases where GHC.Generics is an option, I always take GHC.Generics over TH. Yes, Generics can be slow at times too but this somewhat controllable with various GHC_OPTIONS. Either way, there is no loader and interpreter overhead... and a lot of Generics code compiles in less time than it takes TH just to load `text` or `aeson` ;-).
* Some TH libraries add implicit dependencies that are not tracked by the build system
* GHCi/TH's loader is different than the OS loader, sometimes causing failures if a TH dependency touches C++ libraries
Besides, data outlives code. By orders of magnitude. You seem to be in love with Haskell today, chances are you'll be using a different language in ten years but the data you'll be working with will probably have been around for much longer than that.
Don't fall in love with programming languages, it's a waste of emotional energy.
Of course one can make computation on those types, but it is so un-natural that it scares me :
* BigDecimal for currency, let me laugh
* Date/timestamp without proper casting rules
* Types towers with inheritance, generics, etc. Pfff...
* Still no fine library to represent an address
* Representing mutable ordered lists in SQL databases is still quite painful (possible, sure, but there's so boiler plate code to write)
So the data representation/manipulation problem, which goes with the data longevity you observe, that's something to learn about...
There's no reason to love current programming languages :-( (but I do love Python :-) 3 of course :-))
F#'s units are nice.
> Computing with dates in a sensible way
The new Java time API is pretty good. But honestly my favourite datetime API would have to be Postgres'.
> BigDecimal for currency, let me laugh
Out of curiosity, why?
For BigDecimal, my grief is that it makes code horrible (at least in my experience, I'm still locked in JDK 1.7).
BigDecimal has the problem I see with the rest of my griefs : it is possible to compute things correctly with code (obviously), but the way the code is written is ugly (and painful).
BigDecimal yearly_amount = new BigDecimal("1000.00");
BigDecimal daily_amount = yearly_amount.divide(new BigDecimal("12")); // Beware the rounding issue
money<4> yearly_amount = 1000.00 EUR; // 4 decimals
money<2> daily_amount = yearly_amount / 12; // Beware the rounding issue !
If we all give up and just use mainstream languages, then the future will be filled with copies of mainstream languages.
Actually, as silly as it sounds, I write most my hobby code in C++ because of this. Well, not for a thousand year span but for longevity anyway.
I was astonished when I started learning Common Lisp last year: the language, despite its warts, feels modern and convenient, and the ecosystem - SLIME, asdf & quicklisp - is impressively well designed and surprisingly nice to use.
If you're coming from a Haskell, F#, or even Scala or Ruby background, you might appreciate my functional collections library for CL . It expands the range of code that can easily be written functionally.
Even if you don't have that experience, you might find FSet interesting, but it will take a little longer to wrap your head around.
One of the best, for sure. There are Racket and Clojure in the Lisp family, both comparable to Common Lisp in terms of features. Outside of that, there is Elixir, which in my mind gave Erlang enough additional features to also finally be at that level. Pharo is another language - a modern Smalltalk-inspired, image based GUI environment - which comes close in terms of expressivity, but is nowhere near CL implementations in terms of stability. There's also REBOL and recently also Red. They all differ, of course, but what they have in common is the amount of features such languages offer and the unique kind of synergy you get from each of them. It is still unmatched by currently mainstream dynamically typed languages.
> you might appreciate my functional collections library for CL
Thanks, looks interesting. I'll take a look later. I think one of the most irritating things when I started learning Common Lisp was weird naming of common functions. In Emacs Lisp-land we got dash.el and s.el which made the situation (mostly) better; similar thing was done by Underscore.js. I think something like this could be helpful in CL - maybe your library could fill that role for me.
Given the platform availability I'm pretty sure C++ will eventually reach the living fossil status Lisp and Fortran have.
And you don't really need Emacs for Lisp, there are multiple other options (but yes, I'm using Emacs for C++ too).
Btw., quite a nice cheat sheet. What did you use to make it?
"Btw., quite a nice cheat sheet. What did you use to make it?"
Wow. Never even thought of it in such a context. I'll definitely give it a try.
Question 2: How the F#*$ are you a software developer in Mountain View without a job?