Resigning from the Haskell Platform
mail.haskell.org
mail.haskell.org
sum :: (Num a) => [a] -> a
Which means: for any a which is a number, sum can be used to add up a list of as.
However, going back to the C# example, you'll note we said IEnumerable<T>, not List<T>. In C#, the container is general, but in Haskell it's specific. And since IEnumerable is an interface, this actually means "any type that is enumerable". Haskell has an analogue of IEnumerable called Foldable.
So, what we _really_ wanted sum to say was "sum is a function that, for any container f that is foldable, for any type a that is a number, takes an f of a and gives you an a".
sum :: (Foldable f, Num a) => f a -> a
This is the AMP style version of sum. Some people hate it, I love it.
However, there's another piece of background to this that the email doesn't mention: the Haskell Platform is under attack itself. There's a new solution called stack which is, to my mind, easier to use and less likely to bite you with version conflicts. And whether HP should continue to be the "default" recommended way of starting with Haskell is, at best, controversial.
In short: there's plenty of people who won't miss his work on Haskell Platform, but losing Mark himself is a loss.
A thing about Foldable is that you can fold over it (obviously) but you can't necessarily map over it because in Haskell the general map (fmap of the Functor typeclass) has the law that `map (f1.f2) enum == ((map f1) . (map f2)) enum` but for example for Set this law won't hold because the intermediate set might drop elements identical elements that would not have been identical would the f1.f2 been applied in direct succession. See [0] for an example. Why fmap has this law I don't know, but Functor is super fundamental in Haskell's types so you can bet it's there for a good reason.
Note that this Foldable-Traversable-Functor introduction into Prelude is not complete yet. For example the map in prelude is: `map :: (a -> b) -> [a] -> [b]`. If this movement continues it will possibly be `map :: (Functor f) => (a -> b) -> f a -> f b`. People are super scared of the name Functor, so I think that's why it's not been adopted yet. It should possibly be renamed to Container or Mappable to be more in line with what general developers expect.
Would prelude's map be made equal to fmap however, it would make prelude super powerful. It would suddenly work on any Functor type, not just List.
[0] https://www.fpcomplete.com/user/chad/snippets/random-code-sn...
p.s.: if you don't grok typeclass, call it classclass instead, i.e. class of classes. And then think about how C#'s Interface also defines a class of classes.
The law is the only law of fmap, which is the "structure preserving law". It means that if you apply a function to each element of the structure, you cannot change the shape of the structure.
This structure preserving property means you can safely apply any function (even ones you don't know what they do) and you can be safe you're not losing information beyond what the function takes away.
> It should possibly be renamed to Container or Mappable to be more in line with what general developers expect.
Mappable would be a truthful name. Container is not a good name because far from all Functors are containers. You can map over a lot of things (I/O actions, functions among others) which are not intuitively "containers", unless you revise your intuition of "container" to mean "mappable". :)
The good thing about calling it for what it is – Functor – is an argument commonly lifted by Edward Kmett: when you're honest about what you're dealing with, you instantly give people access to 80 years of collective knowledge about the thing.
[0] https://wiki.haskell.org/Foldable_Traversable_In_Prelude
In practice, I think #2 was a fairly uncommon case, and the fixes were trivial and backwards compatible, so the cost was deemed pretty acceptable. #1 is a point of debate, because 'beginner' needs context (perhaps experienced programmers that are Haskell beginners would get over it quickly, but non-programmers would be substantially more confused, etc). Unfortunately I don't think we have a lot of truly empirical evidence on #1.
- I can fold a list, but what about other types? Which of the similarly or identically named functions dispersed among a bewildering number of library modules is the right one? Are they any different?
- I can fold a Foldable? What is it? Let's find a tutorial about Foldable. Ooh, nice! That takes care of folding anything that can be folded! If I'm not folding a list I only need to find where the relevant Foldable instance is (very easy) or to write one myself (reasonably easy).
It was at that time thought that by keeping prelude simple (pure FP 101 style) it was more accessible to new programmers.
Apparently that mindset was reconsidered recently.
So the big downside is that now if you teach Haskell and want to use Prelude, you'll be forced to almost immediately teach typeclasses.
In my opinion that's not a bad thing at all. Typeclasses put Haskell (and FP in general) right in league with big feature languages like C# and Java. All big features of Haskell are implemented using typeclasses (such as the reputable IO monad). Not teaching that as a fundamental feature right at the beginning only makes the next hurdle of the more category theory heavy advanced features of Haskell that much higher.
find :: (a -> Bool) -> [a] -> Maybe a
find :: Foldable t => (a -> Bool) -> t a -> Maybe a
The obvious beginner question looking at this code is "what's `t a`?", and now you have to explain type classes to someone who just wanted to find an element in a list.There's a list of arguments against FTP compiled on the Haskell wiki: https://ghc.haskell.org/trac/ghc/wiki/Prelude710/List
Instead of explaining that [a] is a List of a's, and then explaining what a list is, you explain that t is a container that is foldable which contains a's.
Does he really need to know the exact details of what a typeclass is?
I'm guessing you have experience with languages that have generic types. The issue with the new Haskell prelude is that not only do you have to grok generic typing in order to write the most basic of Hello World introductory programs, you also have to be able to make sense of the Haddock docs. And that now requires knowledge of the type class syntax as well as basic understanding of generic programming. Whereas previously you could have softened the blow by teaching the special case of "[a] means a collection of a" first, and ramping up to more precise definitions later.
Overall, I'm supportive of the FTP initiative. But I can't shake the thought that the vast majority of people who voted for FTP have long passed the point where they can fully understand the downsides of the change for others.
If someone want to compute lists, it could use a spreadsheet program. It's just better!
This just appears to be a decision of an individual to stick to what they think is the best platform/version for them. Since the individual was also the Release manager, seems like stepping aside was the logical thing to do if they do not prefer the latest version of the language.
https://www.reddit.com/r/haskell/search?q=foldable+traversab...
[0] https://wiki.haskell.org/Foldable_Traversable_In_Prelude
Deep learning, for example, has opened the door to some pretty incredible advances, I'm astonished monthly at least by what people are accomplishing. Stuff that's getting close to the uncanny valley.
I see equally smart people enraptured with Haskell. And, maybe it's just over my head, but so far no practical advance is apparent. To me at least. So, for the sake of the nonbelievers, it would be grand to share some of the hopes that merit the great energies that go into languages like Haskell.
(ps. thanks to Scrollaway for asking, below)
In general terms, Haskell has an unparalleled ability to be both precise and flexible at the same time. At least, that's why I like it.
But, if I look at Deep Learning, I see a freight train to the future. If I look at Haskell, I see a lot of... well, debating about... things.. well I just don't see where it's going. I get the sense that it's a gleeful little clever club that exists as an alternative to doing actual work.
And, where's the counterexample, Haskell is a freight train to where? What's the future that Haskell brings?
This is really a sincere question. I've been programming long enough to feel the limitations of existing tools. But, will humans even be coding in 30 years?
But in the end I don't think it actually enables us to do anything that we haven't been able to do before, so it's probably not as significant as Deep Learning in that respect. To be completely honest, I am not convinced it has huge practical application, as I don't think it will ever be picked up by industry in its current form.
The reason I don't think it will be adopted by industry is that a company's concerns are typically not really aligned with a programming language researcher's concerns. For example, a company probably wants a language that is easy to hire for and easy to train for, and Haskell is definitely neither of these things. Also, from what I've heard, it's very difficult to debug and benchmark Haskell programs, perhaps due to its laziness.
Take all this with a grain of salt though as I've only been learning it for 1 year and read the majority of two books on it; I'm far from an expert.
More generally, learning Haskell (and to a great extent any programming language) is about a different way of doing things. Deep Learning is a thing to do. (It can also be a way of doing other things, but my point is that they're at different levels.)
With that said, your time is limited. Studying Haskell, Deep Learning or Statistics (an option that is criminally underrated) is a choice you have to make, and Haskell isn't necessarily the best use of your time.
If you feel like dipping your toe in the water, though a) install stack https://github.com/commercialhaskell/stack b) try doing this course (http://www.seas.upenn.edu/~cis194/spring13/lectures.html) and _do the homework_. If you find you're enjoying it, you'll have your answer. If you're not enjoying it, it's probably not worth your time.
And for the record, I have no idea what some of the top-flight Haskellers are talking about either. But maybe one day I will.
That's a great question, paulsutter. The great computer scientist Peter Landin in 1965 asked a similar question about the future of programming languages. To answer the question, he imagined a wonderful futuristic programming language with lambda calculus at its core. He named that language ISWIM, and described it in a paper entitled The Next 700 Programming Languages.
Haskell is essentially ISWIM with a Hindley-Milner type system added to it.
https://www.cs.cmu.edu/~crary/819-f09/Landin66.pdf
Haskell is science fiction from 1965. The future that Haskell brings is right now, the 21st century future.
Yes. People will probably still even be writing in C and C++ in 30 years. The same predictions were made about "4GLs" 30 years ago and have not come to pass.
High-level programming has been around for 50ish years, so we probably won't get rid of it for at least another 50.
If the implication is that machine learning will make human programmers obsolete, then no that won't happen. What will happen is that more programmers will be spending more time tweaking, training and debugging/reverse-engineering machine learning systems.
I don't see the connection between Deep Learning and removing humans from the software engineering process, so yes, humans will still be coding in 30 years.
(and some of it will still be done in C, and maybe even in COBOL)
I mean, I understand /why/, but sometimes I really longed for a blunt instrument.
That being said, Haskell has been at the forefront of programming language research since its inception in the 1980s. It may be more academic kind of advances but things have trickled down to mainstream languages, e.g. F# and C# have had influences from Haskell (particularly because Simon Peyton-Jones is employed by Microsoft Research). Scala and other languages have had some influence too. Things such as Parser combinators have emerged from the Haskell world and have been adopted to many programming languages since.
Haskell is exciting because it takes a no-compromises approach to the paradigm it is based on. It's purely functional and lazy, something not taken to such extremes in any prior languages. Whether this is the right(tm) approach to take is open to debate.
If I had to summarize in one sentence: Haskell is a research language that is practical - learning it will make you a better programmer even if you never get the opportunity to use it in your day job.
The advantages appear to be limited to highly complex functional code (i.e. big black boxes of code without side effects). IIRC facebook has a spam filter written using it.
Since most of the industry involves code where the functional aspect isn't all that complex and the side effects are, the practical advances aren't all that relevant for a lot of people.
Except, perhaps, for the impact Haskell is having on other more mainstream languages' design.
You do realize that system you described - Facebook's Sigma - is a real-time, massively concurrent online spam-fighting system, that automatically and implicitly makes your code concurrent for all operations, can optimize it, and has automated caching/batching request mechanisms in place to talk to external systems (Graph databases, SQL, cache servers) in an optimal way while reducing things like round tripping, with naive code? (e.g. it can automagically parallelize and optimize the "N+1 Query Problem" into an efficient query that minimizes duplicated requests and round trips, with no intervention, and the single 'query' can operate over multiple data sources like mentioned previously.) In other words: it does side effects all the time, and makes them manageable in ways you could only dream of in other languages. Did I mention all of that was done in a library? :)
I mean, we definitely have a sales problem, don't get me wrong. We could spit these stories better or clean up the presentation. I can list off a dozen things Haskell is poor at, or probably an infinite number given the time. But you sort of chose literally the worst example in the world to make your point.
I would suggest you actually spend some time with the language in anger. It is not easy. But I've been writing 'real world' software in Haskell for years, and it's no more difficult or 'magical' than any other part of being a software developer. It's just more rewarding because my code works far more often. And working code seems to be something that's rare in the software world these days ;)
That's a great example of a challenging system, analogous to things I've worked on in the past, so I can feel the complexity, and your description also helps me sense the way Haskell is well suited to the task.
So that's cool. I'm glad to hear it. The best example found to date.
And you gotta admit, crdoconnor has a good point that the impact on the world at large may increase as lessons learned in Haskell spill over into the Lesser Languages.
I still hope that some of these super smart guys would take a short break from the language wars. And briefly at least, consider working on things with a more tangible outcome.
It's actually pretty rare for businesses to write highly complex mostly functional code (a spam filter is one exception), and that is where Haskell really shines.
>I would suggest you actually spend some time with the language in anger. It is not easy. But I've been writing 'real world' software in Haskell for years, and it's no more difficult or 'magical' than any other part of being a software developer. It's just more rewarding because my code works far more often. And working code seems to be something that's rare in the software world these days
I've tried it and I've seen its advantages and I'm content to remain with python for the time being. Python's type system isn't as good and that does sometimes cause bugs I wouldn't get in Haskell which I fully understand, but I'd consider the difference incremental. It's not any kind of great leap forward and I think my code would only be slightly less buggy in equivalent Haskell.
On the other hand, Python has a wealth of packages and an ecosystem that Haskell simply doesn't even come close to matching.
Stable, working code is rare, I'll grant you that, and weaker type systems definitely make programming more of a balancing act, but there's a trade off to be made between stronger type systems and not having to rewrite a ton of working code which already exists.
Really? I work with a bunch of languages that does not have controlled side effects, and controlled side effects is the single biggest thing I miss from Haskell. The uncontrolled side effects I swear over daily, if not hourly.
The fact that the order in which I call functions can – undocumentedly – decide whether my program works or crashes is a ridiculous concept. The fact that if I share the wrong piece of data with another part of the application my program starts behaving erratically from having invalid data is odd.
Sharing data should not feel unsafe. Changing the order of method calls should not be a threat.
As long as a function gets the data it wants through explicit parameters, it should work. It shouldn't matter at which point in time I call it, because managing time is really difficult. Managing data is easy.
The controlled side effects in Haskell give you a way to encode these things to give you guarantees and self-documenting code. It gives you opportunities to deal with these problems in sane ways.
Refactoring Haskell code is mostly a matter of symbolic manipulation. A huge chunk of the process doesn't even require me to think about what I'm doing, because I have much more freedom when I don't have to worry about side effects myself. This is good, because I'm bad at thinking and I would like to do it as little as possible. Every single bug that have appeared in my problems have been because I'm bad at thinking.
Sure it does. Well, side effects are boring. It's how you actually do the dance that matters. Here's a few:
- Haskell has a best-in-class concurrency story, with a far greater breadth and depth of techniques and libraries available in most languages (and some, like STM, are realistically impossible otherwise). These include many manners of graph, dataflow, (implicitly auto) parallel and concurrent programming.
- We have a nice blend of epoll based event loops with a multicore runtime, all compiled to native code. This means the traditional 'one thread per client model' is as efficient as any epoll/event loop solution. In practice, it is so cheap because Haskell threads are so cheap that it completely changes how you use concurrency, as it is almost free. It is cheap and easy to add, and the aforementioned toolbox makes it easy to do things - e.g. the `MVar` acts as a one-place blocking queue, which you can use as a lock or shared data structure, as you see fit, between threads.
- Haskell's type system has many features most other 'side effectful languages' don't offer, and even ones that are completely impossible even in things like dynamic languages.
For example, it's possible to use the type system to do things like ensure file handles are tracked statically so they cannot escape a certain scope (a form of 'region management', tracked at compile time). This is actually not even that difficult, honestly.
- Similarly, things like type classes offer a powerful set of abstractions for working with 'effectful code', and allows us to do things like easily separate interfaces from implementation. I can specify a 'Redis' type class and then a concrete implementation of this 'Redis' class, which may or may not be a fake or real. Then I can write functions parameterized only over this type class, and it works with both, and I choose which to use. If I push this further with more classes, individual functions may have a 'Redis' context and a 'MySQL' context to do multiple things; or it may only have a 'Redis' context, and no MySQL. This can be used to enforce separation.
- Lots of use of the type system to enforce all kinds of special cases and invariants. For example, it is entirely possible to use the type system to avoid things like SQL or XSS injection attacks, as done in Yesod. For the extreme version of this, the Ur/Web language takes it to the ultimate conclusion.
- Similarly, it's very easy to encode business logic in Haskell types. You can ensure things like you never mix up a "CustomerID" value with a "ClientID" value, which are really both Ints, but you can make the compiler yell when you mix them up or get something wrong.
- Haskell is a lazy language, meaning it is very easy to refactor, even I/O code. That is because you can pull any piece of code out into a name. Consider this program:
if thing then error "bad things" else 10*2
I can change this to: let x = error "bad things" if thing then x else 10*2
You cannot do this in a non lazy language. Well, you can, but it gets miserable pretty quick. Furthermore this applies to any subexpression; suppose I have a program: h <- openThing "foo"
doStuff h
... some more stuff ...
undoStuff h
closeThing h
I can change this to:
let begin f =
h <- openThing f
doStuff h
let end h =
undoStuff h
closeThing h
h <- begin "foo"
... some more stuff ...
end h
Again, this is not valid if your language is strict. But these patterns are very obvious and common when you can freely rearrange any expression. Then you can see the final abstraction easily: let withThing x f =
h <- openThing f
doStuff h
f
undoStuff h
closeThing h
let stuff = ... do some stuff ...
withThing "foo" stuff
This particular point requires a lot of experience to truly appreciate in practice IMO. But in practice it means you can freely move code anywhere at no cost, even any I/O code, so you can very easily abstract over it like above. In non-lazy languages, this becomes significantly more tedious.> It's actually pretty rare for businesses to write highly complex mostly functional code (a spam filter is one exception), and that is where Haskell really shines.
The term 'mostly functional code' is meaningless, because we have not even defined what it means, so it's not really useful for me to try and convince you of anything :)
Again, you do realize the 'spam filter' that Facebook produced isn't just some weekend Bayesian spam filter, right? Actual software at the scale is quite complex. I'd assume it handles at minimum tens to hundreds of millions of requests a day and integrates with millions of lines of internal code. I'm probably lowballing that, even. It's a serious piece of software.
> I've tried it and I've seen its advantages and I'm content to remain with python for the time being. Python's type system isn't as good and that does sometimes cause bugs I wouldn't get in Haskell which I fully understand, but I'd consider the difference incremental. It's not any kind of great leap forward and I think my code would only be slightly less buggy in equivalent Haskell.
That's fine. But based on what I've seen (to be completely honest, not as an insult, you do not give the impression of someone who has spent extensive time with it[1]), I'd say you're greatly underestimating exactly what it is capable of, as well as precisely what capabilities it offers in the first place.
[1] The fact it should take you so long to understand it is a problem in its own way, and we should certainly keep seeking to narrow the gap between "regular ordinary programmer person" and "someone with a weird disposition for Haskell"-slash-"Someone who has way too much time"-slash-"Someone who is super persistent". Totally a problem.
> On the other hand, Python has a wealth of packages and an ecosystem that Haskell simply doesn't even come close to matching.
This is certainly a real complaint for a lot of domains. It's one of the many things I could complain about. In other domains, Haskell is excellent and has quite a lot of good options. It seems to be particularly popular for web developers these days. It's definitely still pretty terrible if you want like, QT bindings on Windows.
I can handle epoll based code without problems anyway.
The whole "file handles" can't escape a certain scope sounds like what python's with statement does.
The whole it's amazing that you can "encode business logic in types" thing I really don't get. That's basically the selling point of object oriented code.
Similarly, SQL injection is a problem that largely plagues dumb PHP code and is close to irrelevant if you use a half-way decent ORM in any language.
>The term 'mostly functional code' is meaningless
Any code that is mostly made up of functional programming, but still has some state handling code. I think it's pretty clear.
>Actual software at the scale is quite complex.
Gee maybe that's why I said it was complex.
>That's fine. But based on what I've seen (to be completely honest, not as an insult, you do not give the impression of someone who has spent extensive time with it[1]), I'd say you're greatly underestimating exactly what it is capable of, as well as precisely what capabilities it offers in the first place.
No, I haven't used it extensively. I've played with it.
I honestly think if it the benefits you tout were as great as you seem to think they are then there would be a far greater wealth of practical software written in it.
I know of one website (a local fashion retailer) and Facebook's spam filter. That's about it.
It is incredibly easy to return a file handle out of a with statement. There is nothing in place other than programmer discipline preventing you from doing so, and your program blows up in... interesting ways.
With OOP languages those are mostly runtime errors rather than compile time errors. Encoding logic into the type system means that many application logic errors will be caught at compile time before your application goes into production.
> I honestly think if it the benefits you tout were as great as you seem to think they are then there would be a far greater wealth of practical software written in it.
I honestly think if PHP were as bad as it seems there would be far less practical software written in it. Popularity doesn't imply quality just like lack of popularity doesn't imply lack of quality.
And nice libraries. But other languages have them bigger and of similar quality.
It's not a fundamental flaw it's a change. Basically in the early days of Haskell they decided to make much of the prelude (the builtins) work on the concrete type "list" rather than on more abstract types for beginner simplicity, with more abstract "interfaces" like Foldable not shown upfront, with the attendant duplication as each function of the prelude now has a more abstract duplicate somewhere else.
The FTP change reverses this and alters the prelude to operate on abstract types rather than concrete ones, this somewhat increases the initial learning experience[0] but it doesn't really change the language itself.
For C# equivalence, imagine if all the most easily accessible functions operated on the concrete `List` to avoid having to introduce interfaces and all had duplicates taking an IEnumerable instead (that doesn't quite work as C# uses methods but there you are).
And surely if that's a "fundamental flaw" of Haskell, you've wasted your time with C# and its fundamental flaw of non-generic System.Collections
[0] for complete beginners with no concept of abstract types I guess? For Haskell beginners coming from other languages it doesn't seem like a big issue, just a matter of how abstract types which is already an issue between languages anyway e.g. where Haskell has Foldable C# has IEnumerable, Ruby has Enumerable, Java and Python have Iterable, ...
Thanks! Considering 'List' is one of the few structures of FP I understand, that makes actual sense.
I would guess that Ocaml might be better in unixy environment while sharing similar features to F#?
Core language works fine and no dependence on VS. There are packages for most distros. Libraries outside the core language are a bit hit and miss, but you'll find libraries for most things you want to do.
If you have a Windows project where you've been NuGetting stuff from all over the place, porting might be a bit of a pain.
Besides, you would also be asserting that F# does not have that flaw. I don't believe you have that evidence either.
That said, F# is pretty nice. It's opt-in laziness for .NET compatibility but laziness is pervasive. There's no forced purity though. On the plus side it's easy to interact with anything that has .NET bindings.
I started learning haskell 3 years ago with no background in CS nor in mathematical expertise. So I feel like I'm still a noob toying with ghc until late.
But I welcome that change with a big smile! In my opinion it resolves the list problem (who can be a jail sometimes). As a newcomer I always started with lists which often ended as a bad choice but I learned it that way...
Like: "Oh, wait.. those lists were cools but... WHAT? I need to change everything because just now there are too limited? Fffuuuhh..."
I'm pretty curious, can someone summarize for me, what was the deal with FTP? What are the pros and cons, and why are people upset about it? That'd be really nice, thanks.
Scala has awful types. GHC 7.10.2 change is still elegant.
If you, like me, have no idea what this is about, just go back to coding in one of those subtheoretical languages for feeble minded norms, like me.
I'm sure these guys are doing some REALLY IMPORTANT WORK with a language as obscure as that. Way over my head, I'm sure.
EDIT: Scrollaway, thanks for asking. I don't really have a beef with Haskell itself, I just think its tragic that so many smart people are drawn to something that has .. well.. let's just say, I'd love to hear the practical aspects of Haskell.
All languages and paradigms can be obscure to outsiders. Just take a look at http://programmers.stackexchange.com/questions/tagged/object...
Even if you wanted more function, you couldn't have it, because there isn't. And yet, you find that it has no function. None!
Water, water, every where,
And all the boards did shrink;
Water, water, every where,
Nor any drop to drink.