> Array programming is similar to functional programming – the primary way to control execution involves composition of functions – but APL tends to encourage the reliance on global properties and sweeping operations rather than low-level recursion4.
This AoC solution is, indeed, quite the functionista! Better yet, it leans heavily into point-free expressions. The style is pretty popular amongst APL language enthusiasts and puzzlers.
That said, you actually see quite different APL styles in the wild:
- Pointed declarative style, also a popular with functional programmers (e.g. anything like this[0] from the dfns workspace)
- Imperative, structured programming, very common in legacy production systems (e.g. this[1] OpenAI API interface)
- Object-oriented, also common in somewhat newer production environments (e.g. the HTTP interface[2])
- Data-parallel style (e.g. Co-dfns[3])
Heck, APL even has lexical and dynamic scope coexisting together. IMHO, it's truly underrated as a language innovator.
My favorite language used to interpret my most hated language (used both professionally).
There are several things I disagree with regarding Haskell but it's understandable given that this is OP's first time using the language (like a "monad's internal state"), but I want to highlight one particular observation:
> This uncertainty of time of evaluation also makes catching errors difficult, because calling catch on the function that throws the error will not necessarily catch that error
It's important to distinguish between imprecise exceptions (ex. calls to `error `, `undefined`, and the like) and synchronous exceptions (async exceptions are not important for the article).
> Catch must be called on the function that forces evaluation on that error. This is something that is hard to trace, and something that types don’t help much with.
The types are actually the most important part here! Synchronous exceptions cannot be thrown by pure code (as long as we're not dealing with escape hatches like `unsafePerformIO`), while IO code can throw and catch all kind of exceptions .
Regarding catch, yes, I agree types help, but they can help even more! I suggest an IO-wrapper effect system (mine is called Bluefin; effectful is also a good choice). Then there is absolutely no ambiguity about where an exception can be handled. There is exactly one place -- no more, no less. It makes dealing with exceptions very easy.
Seeing "all built-in functions and operators are single unicode symbols" stood out to me, given that APL existed well before Unicode did. It's not that it's wrong today, but that wasn't always the case. My father used APL back in high school, and that was before the earliest year mentioned in the "History" section of the Unicode Wikipedia article.
Unicode inherited most of APL's encoding sets from EBCDIC code pages. Almost no one would choose to work in EBCDIC today, so it is practical to just say Unicode as the last encoding left standing (for everyone not working on legacy APL code on [emulated] IBM mainframe hardware).
Is there an implementation of an APL language (or other any other array language) written in *readable* C that is around 1000 LoC? There are for LISP, FORTH, Prolog, TCL and the like.
Unlikely, at least for what I think you mean by "readable" here.
APL isn't really one of these exhibitions of computational simplicity in the way of the languages you mention. It's inventor, Kenneth Iverson, was more focused on the human side of thinking in and using the language.
Forth, Lisp, et al are quite easy to implement, but they require considerable library layers on top to make them useful for expressing application-level logic, even if we just focus on the pure functions. APL, on the other hand, has a larger core set of primitives, but you're then immediately able to concisely express high-level application logic.
Are you looking for a kind of reference implementation for learning purposes? If so, I'd say the best route is just go with the docs. Arguably the Co-dfns compiler is a precise spec, but it's notably alien to non-practitioners.
Any pointers on how to get better at expressing high-level application logic in APL? Any good resources on programming in APL? So far I have only found tutorials and basic stuff for learning APL but not much on applying APL. I am slowly improving and think I sort of get it but probably don't.
Not that I know of, unfortunately. This is, IMHO, the biggest pain point of APL pedagogy at the moment. I'm actually working on some resources, but they're still gestating.
For non-event driven systems, the short story is to organize application state as a global database of inverted tables and progressively normalize them such that short APL expressions carry the domain semantics you want.
For event driven systems, we have token enumeration over state machines, which can be expressed as literal Branches to state blocks.
Granted, the above likely doesn't communicate well unless you're already primed with all the necessary ideas. If you're interested, I'm willing to chat. Email is in my profile description.
>IMHO, the biggest pain point of APL pedagogy at the moment
It is the one that always trips me up. I just started in on my third attempt at learning APL/array languages, both previous times I got to the same point where I was mostly at a loss of how to apply it all. So I move on and forget all that I learned until the next time and have to start over. Thankfully the last attempt seems to have mostly stuck as far as keyboard layout goes, makes progress much quicker.
I may take you up on that email offer once I get a bit further along in this current attempt, can't quite form reasonable questions yet and only know what tripped me up in the previous attempts. I believe you are a regular on APL Orchard? I will be joining it soon so perhaps will see you there.
The logic of the system instead of the pieces of the system; how the language's core data structure applies/relates towards expressing that system. I could very well be overthinking things and seeing some sort of magic which is not there but this line in the previous response to me, makes me think I am still missing a piece of the puzzle:
>organize application state as a global database of inverted tables and progressively normalize them such that short APL expressions carry the domain semantics you want.
Ok. I have some idea I think of where you are at, so I will give it a shot. I think this sort of thing is an emergent property in the design of APL applications, and so there's nothing to "see" in terms of an example unless you can see that design process.
But first, "database" here is just the list of global variables. If that wasn't obvious, it is important.
My application processes weblogs, and "clicks" is the bit-array of which event was a click (redirect), as opposed to having a variable called "weblog" which contains a list of records each possibly having an event-type field.
Normalizing them that acknowledges that the weblog (input) probably looked like the latter, but it's easier to do work on the former. APL makes that transformation very easy: Just rotate the table. In k this is flip. Simples.
Those "domain semantics" are simply the thing I want to do with "clicks" which in my application comes from the business (users), so I want them to provide a bunch of rules to do that.
Look carefully at the tables, because they're given in a slightly different way, but they are the same. And these are all of them, so it should be obvious at this point you can represent any boolean operation against any matrix of variables with a matrix of these numbers.
For example, you might have a sql-like expression (from a user of your application) of x=y, and x<y and so on that you want to use to filter some data set.
Now if you are to think about how you might do this in Javascript (for example; probably in scheme too) you would probably organise such a table as a chain of closures. And I think if you look at any ORM in just about any language you'll see this kind of pattern (maybe they use classes or use a tree, but these are obviously the same as closures), but such a tree can only be traversed, and the closure can only be called. Maybe you can batch or shard, but that's it, and since I would bet there are a lot of dependant loads/branching in this tree of closures, it is slow.
But if you understand that this tree is also a matrix of boolean operators, it is obviously parallelisable. And each operation is simple/cache-friendly and so therefore fast. This leads to your "queries" being a set of projected indexes or bitmaps (whichever is convenient), which you probably also store in global variables someplace (because that is convenient) while you're doing what you need to do (make xml, json, bar charts, run programs, whatever)
I may be reading too much into this but it sounds like you’re searching for templates to stimulate ideas similar to how there are examples for smaller puzzle type problems.
I think most sizable stuff is proprietary. I implemented an lsp in an open source K which uses json/rpc. But the open source K is probably best considered a hobby project.
Beyond what others have mentioned, I think another big differentiating factor between APL and the rest of those languages is that APL isn't focused on allowing the user to expand the language meaningfully, but rather on being a well-rounded language by itself (which is how it can be reasonably useful without objects with named fields, mutation, explicit loops (or only gotos in APLs infancy!), no first-class functions, no macros, and only one level of higher-order function (though of course most APL implementations have some of those anyway)).
As such there's really no pretty "core" that pulls its weight to implement in 1000LoC and is useful for much.
Couple that with an implementation of whatever primitives you want, and a simple AST walker, and you've got a simple small APL interpreter. But those primitive implementations already take a good chunk of code, and adding variables/functions/nested functions/scoping/array formatting/etc adds more and more bits of independent code.
Perhaps if you accept defining bits in the language in itself via a bootstrap step, BQN is a good candicate for existing small implementations - a BQN vm + minimal primitive set is ~500LoC of JS[0] (second half of the file is what you could call the native components of a stdlib), 2KLoC for first public commit of a C impl[1], both of those having the rest of the primitives being self-hosted[2], and the compiler (source text → bytecode) being self-hosted too[3]. (the C impl also used r0.bqn for even less required native primitives, but modern CBQN uses very little of even r1.bqn, having most important things native and heavily optimized)
> Apparently Haskell’s performance isn’t that bad, but I don’t plan on using Haskell for anything that is remotely performance-sensitive. Trying to optimize Haskell code does sound like an interesting problem, but it might be a lost cause.
When the dude uses `foldl` over lists and `foldr` with `(*)` (numeric product) it is not the language that's the lost cause.
In case anyone who doesn't know Haskell: both of these are beginner level mistakes. Using `foldl` causes space leaks and turns your O(1) space algorithm to O(N) space for no good reason. And using `foldr` over lists is good when you are dealing with unevaluated lists and want list fusion, but not when they already exist in memory and will continue to do so. And that doesn't even include the obviously wrong choice of data structure, built-in Haskell lists are singly-linked lists not arrays. There are Array types and Vector types (both come with GHC so no extra dependency needed) that are more appropriate for implementing APL in the first place.
> And using `foldr` over lists is good when you are dealing with unevaluated lists and want list fusion, but not when they already exist in memory and will continue to do so.
In short: use foldl’ when you’re iterating through a list with state. foldr can be used for anything else, but I recommend it for experts only. For non-experts I expect it’s easier to use for_. For more details about that see my article “Scrap your iteration combinators”.
Is it really easier to use for_? It forces you to think about effects rather than pure data. So you end up packaging data into effects through State or similar monads. So is it really easier if you force people to use Monad (well technically Applicative)?
Usually you want `foldl'` (with ' at the end), the strict version of `foldl`. It prevents the creation of intermediate thunks, so effectively a tail recursive iteration over the list in constant space.
`foldr` I almost never use, but it would be for: the return value is a lazy list and I will only need to evaluate a prefix.
This is what happens when you let Mathematicians name things on chalkboards. They don't want to run out of chalk and they get tired of spelling whole words very easily so they use short names and silly symbols. The name foldl' is "just" "fold left prime". Remember ' means "prime" from calculus class and thinking that was silly even then? Accidentally infected Haskell at a young age.
Yeah it's definitely unusual to allow ' to be part of the name of a variable, especially considering that it is, like C, the quote for character types.
> When the dude uses `foldl` over lists and `foldr` with `(*)` (numeric product) it is not the language that's the lost cause.
This is a great example of Haskell's community being toxic. The author clearly mentioned they're new to the language, so calling them a "lost cause" for making a beginner mistake is elitist snobbery.
I usually don't point these things out and just move on with my life, but I went to a Haskell conference last year and was surprised that many Haskell proponents are not aware of the effects of this attitude towards newcomers.
Can I ask which conference? Did people behave towards you in that way at that conference, or are you referring to behaviour online? I will try to use whatever authority I have in the Haskell community to improve the situation.
(Still, hopefully in this case it's clear from instig007's reply that it's not a member of the Haskell community behaving in that way.)
This is almost exclusively just online behaviour. Everyone I met in person is very nice :).
The conference I mentioned was ZuriHac. After the key-note Q&A there was a small hallway discussion around how to grow the adoption / reach of Haskell. The conversation revolved around mostly technical points (like how Haskell is superior to x, because of y). What I found interesting was that there was little to no talk about the steep learning curve, developer ergonomics or business use-cases.
The thing is, if someone has not yet learned about functional programming, strong type systems or category theory, why / how would they see the advantages or the power of pure functions, lazy evaluation, Monads, etc. At the same time, their opinions or struggles are often dismissed due to their lack of knowledge. The parent comment is a prime example of this.
Newcomers need the self-awareness to understand that they are newcomers and that their opinions are more often than not wrong. This author doesn't have that humility.
It is simply aggravating to see newcomers without humility speak with an authoritative tone on subjects they barely know.
> calling them a "lost cause" for making a beginner mistake is elitist snobbery.
I wonder how do you call the practice of complete beginners spreading FUD and suggesting to their readers that something in the language is "a lost cause", all whilst having neither enough knoweldge nor sufficient practice to make assumptions of this kind.
> This is a great example of Haskell's community being toxic
To be clear: I don't represent haskell community, I'm not part of it, and I couldn't care less about it. It just so happened that I saw the author inflating their credentials at the expense of the language via spreading FUD, that the beginners you seem to care about are susceptible to, and I didn't like it.
If you get triggered by the expressed dissatisfaction with the author's unsubstantiated presumptuousness, reflected back at them in a style and manner they allowed themselves to talk about the thing they don't know about, then it's purely on you and your infantilism.
On a semi-related topic: I tried learning Haskell this past weekend out of curiosity that I last tried it some 10+ years ago while still in college.
I found resources for it scant. Coming from more modern languages/tooling like Go/Rust, I also struggled quite a bit with installation and the build/package system.
I tried the stack template generator for yesod/sqlite and after some 15 minutes of it installing yet another GHC version and building, I eventually ctrl+C'd and closed out of the window.
Maybe this was a unique experience, but I'd love some guidance on how to be successful with Haskell. I've primarily spent most of my professional years building web services, so that was the first place I went to. However, I was taken aback by how seemingly awful the setup and devex was for me. I've always been interested in functional programming, and was looking to sink my teeth in to a language where there is no other option.
As for being successful, there are several nice books, and several active forums. I've gotten good answers on the Libera IRC network #haskell channel, and on the Haskell matrix channel #haskell:matrix.org
I loved the book "Real World Haskell" [1] when it first came out in 2008. It feels like a shame it hasn't aged well and there hasn't been an updated edition since then. Especially because it was focused on things like "here's how you build example web services" as a good place to discuss everything else by having the end goal of the book's "narrative" structure be real world things you might build. It may still help to glance at a little, but things have advanced so much in the decade and a half since the book was written it is hard to recommend, but it still feels like there should be a book like it updated for current day to be out there to more heartily recommend. If there is one I don't know of it, but I haven't followed Haskell as much as I'd like in my professional career.
My understanding is that Cabal has more or less supplanted Stack. Use GHCup to install everything, then use `cabal init`, `cabal run`, or `cabal repl` like you would in Go/Rust.
Stack builds on top of Cabal, and used to solve a bunch of problems, but the reasons for it's existence are no longer super relevant. It still works totally fine if that's your thing though.
That is so interesting and is a point where GPT has failed me if this is true.
My understanding was the stack was the choice due to having better ergonomics over cabal. Apparently that isn't true? I Found that stack init was pretty decent at setting up a project structure, but can't say I tried cabal init.
I initially installed ghcup via homebrew but found that did not set things up correctly and had to follow the install from their site, which made things work more smoothly.
I learned using the Haskell Programming from First Principles book (haskellbook.com). I don't think it goes into web development, but it certainly goes through the basic project setup.
Do you think you would have benefitted from a resource like the Rust book? I've been toying with the idea of writing something similar and donating it to the Haskell Foundation
I've seen this book referenced a few times and is quite large from what I've seen.
Not opposed to checking it out, but to your question: I really like the Rust book and how easy it is to find and read. It feels modern, up to date, and the standard for how to learn Rust.
Please don't dig up historical comments in order to diminish someone's present-day comments or work. We can't know what has happened between then and now.
Isn't referencing a source exactly the right way to go about pointing out someone is essentially lying about their background/credentials? I'm surprised people do not care about accuracy.
Thanks! I didn't actually build it myself but a professor and other student were also involved. When I joined the project the decision was already made: the professor wanted to use APL and we were using an old CPU architecture book as reference that used APL (Gerritt A. Blaauw, Frederick P. Brooks Jr. Frend, Computer Architecture: Concepts and Evolution 1st Edition).
We almost got the PDP-11 working albeit some extensions like floating point arithmetic.
>GNU is free but pretty much abandoned. Support for Windows was (is?) nonexistent.
GNU APL was never abandoned, dev just went a long time without doing a proper release. I believe the Windows issue is just with cygwin, never looked into it since I don't use Windows.
a) “professional” writ large often encompasses academic research, even though it’s also often specifically used in contrast. Language is weird like that. Former and current academics like to have a term for all the stuff we’ve been paid to do, and we usually default to “professional experience” (though current academics do usually say “research experience” because you’re right that professional has the default connotation of corporate employment).
b) the project seems to have been over 2000 lines of APL. That’s not the “small” student project you’re implying, in any language, and in APL that’s quite substantial.
So you go through my profile and assume that you know my professional background? What makes you think that that's the only project where I've used APL?
I don't think he went through your profile, suspect he just remembered the discussion he had with you in the linked thread. But how about we end this? it is not productive or interesting.
I remembered it, and it seems like a reasonable assumption that your first experience of APL being so bad would put you off doing any more in the future.
This AoC solution is, indeed, quite the functionista! Better yet, it leans heavily into point-free expressions. The style is pretty popular amongst APL language enthusiasts and puzzlers.
That said, you actually see quite different APL styles in the wild:
- Pointed declarative style, also a popular with functional programmers (e.g. anything like this[0] from the dfns workspace)
- Imperative, structured programming, very common in legacy production systems (e.g. this[1] OpenAI API interface)
- Object-oriented, also common in somewhat newer production environments (e.g. the HTTP interface[2])
- Data-parallel style (e.g. Co-dfns[3])
Heck, APL even has lexical and dynamic scope coexisting together. IMHO, it's truly underrated as a language innovator.
[0]:https://dfns.dyalog.com/c_match.htm
[1]:https://github.com/Dyalog/OpenAI/blob/main/source/OpenAI.apl...
[2]:https://github.com/Dyalog/HttpCommand/blob/master/source/Htt...
[3]:https://github.com/Co-dfns/Co-dfns/blob/master/cmp/PS.apl
There are several things I disagree with regarding Haskell but it's understandable given that this is OP's first time using the language (like a "monad's internal state"), but I want to highlight one particular observation:
> This uncertainty of time of evaluation also makes catching errors difficult, because calling catch on the function that throws the error will not necessarily catch that error
It's important to distinguish between imprecise exceptions (ex. calls to `error `, `undefined`, and the like) and synchronous exceptions (async exceptions are not important for the article).
> Catch must be called on the function that forces evaluation on that error. This is something that is hard to trace, and something that types don’t help much with.
The types are actually the most important part here! Synchronous exceptions cannot be thrown by pure code (as long as we're not dealing with escape hatches like `unsafePerformIO`), while IO code can throw and catch all kind of exceptions .
https://hackage.haskell.org/package/bluefin-0.0.16.0/docs/Bl...
https://www.jsoftware.com/ioj/iojATW.htm
https://github.com/kparc/ksimple/blob/main/ref/a.c
Slightly less factiously, the ksimple repository has a version with comments.
https://github.com/kparc/ksimple
https://github.com/kparc/ksimple/blob/main/a.c
Note, these aren't APL, but they are in the same family of array languages.
APL isn't really one of these exhibitions of computational simplicity in the way of the languages you mention. It's inventor, Kenneth Iverson, was more focused on the human side of thinking in and using the language.
Forth, Lisp, et al are quite easy to implement, but they require considerable library layers on top to make them useful for expressing application-level logic, even if we just focus on the pure functions. APL, on the other hand, has a larger core set of primitives, but you're then immediately able to concisely express high-level application logic.
Are you looking for a kind of reference implementation for learning purposes? If so, I'd say the best route is just go with the docs. Arguably the Co-dfns compiler is a precise spec, but it's notably alien to non-practitioners.
For non-event driven systems, the short story is to organize application state as a global database of inverted tables and progressively normalize them such that short APL expressions carry the domain semantics you want.
For event driven systems, we have token enumeration over state machines, which can be expressed as literal Branches to state blocks.
Granted, the above likely doesn't communicate well unless you're already primed with all the necessary ideas. If you're interested, I'm willing to chat. Email is in my profile description.
source: Current day-to-day is greenfield APL dev.
It is the one that always trips me up. I just started in on my third attempt at learning APL/array languages, both previous times I got to the same point where I was mostly at a loss of how to apply it all. So I move on and forget all that I learned until the next time and have to start over. Thankfully the last attempt seems to have mostly stuck as far as keyboard layout goes, makes progress much quicker.
I may take you up on that email offer once I get a bit further along in this current attempt, can't quite form reasonable questions yet and only know what tripped me up in the previous attempts. I believe you are a regular on APL Orchard? I will be joining it soon so perhaps will see you there.
In the off chance you've not see this: https://aplwiki.com/wiki/Chat_rooms_and_forums
>organize application state as a global database of inverted tables and progressively normalize them such that short APL expressions carry the domain semantics you want.
But first, "database" here is just the list of global variables. If that wasn't obvious, it is important.
My application processes weblogs, and "clicks" is the bit-array of which event was a click (redirect), as opposed to having a variable called "weblog" which contains a list of records each possibly having an event-type field.
Normalizing them that acknowledges that the weblog (input) probably looked like the latter, but it's easier to do work on the former. APL makes that transformation very easy: Just rotate the table. In k this is flip. Simples.
Those "domain semantics" are simply the thing I want to do with "clicks" which in my application comes from the business (users), so I want them to provide a bunch of rules to do that.
Now with that in mind, take a look here:
https://code.jsoftware.com/wiki/Vocabulary/bdot#bitwise
and here:
http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec...
Look carefully at the tables, because they're given in a slightly different way, but they are the same. And these are all of them, so it should be obvious at this point you can represent any boolean operation against any matrix of variables with a matrix of these numbers.
For example, you might have a sql-like expression (from a user of your application) of x=y, and x<y and so on that you want to use to filter some data set.
Now if you are to think about how you might do this in Javascript (for example; probably in scheme too) you would probably organise such a table as a chain of closures. And I think if you look at any ORM in just about any language you'll see this kind of pattern (maybe they use classes or use a tree, but these are obviously the same as closures), but such a tree can only be traversed, and the closure can only be called. Maybe you can batch or shard, but that's it, and since I would bet there are a lot of dependant loads/branching in this tree of closures, it is slow.
But if you understand that this tree is also a matrix of boolean operators, it is obviously parallelisable. And each operation is simple/cache-friendly and so therefore fast. This leads to your "queries" being a set of projected indexes or bitmaps (whichever is convenient), which you probably also store in global variables someplace (because that is convenient) while you're doing what you need to do (make xml, json, bar charts, run programs, whatever)
I think most sizable stuff is proprietary. I implemented an lsp in an open source K which uses json/rpc. But the open source K is probably best considered a hobby project.
https://github.com/gitonthescene/ngnk-lsp/blob/kpath/k/lsp.k
You might consider joining one of the APL forums if you haven’t already.
https://mathspp.com/blog/tag:lsbasi-apl#body-wrapper
The expansion is mechanical and thus not really at attempt at readability.
As such there's really no pretty "core" that pulls its weight to implement in 1000LoC and is useful for much.
Here's a simple minimal APL parser in JS that I wrote once to display one way of parsing APL: https://gist.github.com/dzaima/5130955a1c2065aa1a94a4707b309...
Couple that with an implementation of whatever primitives you want, and a simple AST walker, and you've got a simple small APL interpreter. But those primitive implementations already take a good chunk of code, and adding variables/functions/nested functions/scoping/array formatting/etc adds more and more bits of independent code.
Perhaps if you accept defining bits in the language in itself via a bootstrap step, BQN is a good candicate for existing small implementations - a BQN vm + minimal primitive set is ~500LoC of JS[0] (second half of the file is what you could call the native components of a stdlib), 2KLoC for first public commit of a C impl[1], both of those having the rest of the primitives being self-hosted[2], and the compiler (source text → bytecode) being self-hosted too[3]. (the C impl also used r0.bqn for even less required native primitives, but modern CBQN uses very little of even r1.bqn, having most important things native and heavily optimized)
[0]: https://github.com/mlochbaum/BQN/blob/master/docs/bqn.js though earlier revisions might be more readable
[1]: https://github.com/dzaima/CBQN/tree/bad822447f703a584fe7338d...
[2]: https://github.com/mlochbaum/BQN/blob/master/src/r1.bqn (note that while this has syntax that looks like assigning to primitives, that's not actual BQN syntax and is transpiled away)
[3]: https://github.com/mlochbaum/BQN/blob/master/src/c.bqn
i think the first raku (perl6) parser (pugs) was written in Haskell, certainly all the team learned Haskell before they started
When the dude uses `foldl` over lists and `foldr` with `(*)` (numeric product) it is not the language that's the lost cause.
What's the preffered approach?
https://h2.jaguarpaw.co.uk/posts/foldl-traverses-state-foldr...
In short: use foldl’ when you’re iterating through a list with state. foldr can be used for anything else, but I recommend it for experts only. For non-experts I expect it’s easier to use for_. For more details about that see my article “Scrap your iteration combinators”.
https://h2.jaguarpaw.co.uk/posts/scrap-your-iteration-combin...
`foldr` I almost never use, but it would be for: the return value is a lazy list and I will only need to evaluate a prefix.
Doubly so with APL!
This is a great example of Haskell's community being toxic. The author clearly mentioned they're new to the language, so calling them a "lost cause" for making a beginner mistake is elitist snobbery.
I usually don't point these things out and just move on with my life, but I went to a Haskell conference last year and was surprised that many Haskell proponents are not aware of the effects of this attitude towards newcomers.
(Still, hopefully in this case it's clear from instig007's reply that it's not a member of the Haskell community behaving in that way.)
The conference I mentioned was ZuriHac. After the key-note Q&A there was a small hallway discussion around how to grow the adoption / reach of Haskell. The conversation revolved around mostly technical points (like how Haskell is superior to x, because of y). What I found interesting was that there was little to no talk about the steep learning curve, developer ergonomics or business use-cases.
The thing is, if someone has not yet learned about functional programming, strong type systems or category theory, why / how would they see the advantages or the power of pure functions, lazy evaluation, Monads, etc. At the same time, their opinions or struggles are often dismissed due to their lack of knowledge. The parent comment is a prime example of this.
Edit: This is a great 10-minute talk that touches on the general topic: https://www.hytradboi.com/2025/419859c5-6a8f-4a49-b324-0f225... She covers a lot of this better than I can.
It is simply aggravating to see newcomers without humility speak with an authoritative tone on subjects they barely know.
I wonder how do you call the practice of complete beginners spreading FUD and suggesting to their readers that something in the language is "a lost cause", all whilst having neither enough knoweldge nor sufficient practice to make assumptions of this kind.
> This is a great example of Haskell's community being toxic
To be clear: I don't represent haskell community, I'm not part of it, and I couldn't care less about it. It just so happened that I saw the author inflating their credentials at the expense of the language via spreading FUD, that the beginners you seem to care about are susceptible to, and I didn't like it.
If you get triggered by the expressed dissatisfaction with the author's unsubstantiated presumptuousness, reflected back at them in a style and manner they allowed themselves to talk about the thing they don't know about, then it's purely on you and your infantilism.
On a semi-related topic: I tried learning Haskell this past weekend out of curiosity that I last tried it some 10+ years ago while still in college.
I found resources for it scant. Coming from more modern languages/tooling like Go/Rust, I also struggled quite a bit with installation and the build/package system.
I tried the stack template generator for yesod/sqlite and after some 15 minutes of it installing yet another GHC version and building, I eventually ctrl+C'd and closed out of the window.
Maybe this was a unique experience, but I'd love some guidance on how to be successful with Haskell. I've primarily spent most of my professional years building web services, so that was the first place I went to. However, I was taken aback by how seemingly awful the setup and devex was for me. I've always been interested in functional programming, and was looking to sink my teeth in to a language where there is no other option.
As for being successful, there are several nice books, and several active forums. I've gotten good answers on the Libera IRC network #haskell channel, and on the Haskell matrix channel #haskell:matrix.org
If you want to get started without installing anything, there's the exercism track: https://exercism.org/tracks/haskell
I've heard good things about Brent Yorgey's Haskell course ( https://www.cis.upenn.edu/~cis1940/spring13/lectures.html ) but haven't tried it myself.
[1] https://book.realworldhaskell.org/
Stack builds on top of Cabal, and used to solve a bunch of problems, but the reasons for it's existence are no longer super relevant. It still works totally fine if that's your thing though.
I initially installed ghcup via homebrew but found that did not set things up correctly and had to follow the install from their site, which made things work more smoothly.
Do you think you would have benefitted from a resource like the Rust book? I've been toying with the idea of writing something similar and donating it to the Haskell Foundation
Not opposed to checking it out, but to your question: I really like the Rust book and how easy it is to find and read. It feels modern, up to date, and the standard for how to learn Rust.
After checking it out this is definitely on the way to what I"m looking for. Direct, no-nonsense examples that are easy to find and grok.
We detached this subthread from https://news.ycombinator.com/item?id=44196205 and marked it off topic.
We almost got the PDP-11 working albeit some extensions like floating point arithmetic.
>GNU is free but pretty much abandoned. Support for Windows was (is?) nonexistent.
GNU APL was never abandoned, dev just went a long time without doing a proper release. I believe the Windows issue is just with cygwin, never looked into it since I don't use Windows.
a) “professional” writ large often encompasses academic research, even though it’s also often specifically used in contrast. Language is weird like that. Former and current academics like to have a term for all the stuff we’ve been paid to do, and we usually default to “professional experience” (though current academics do usually say “research experience” because you’re right that professional has the default connotation of corporate employment).
b) the project seems to have been over 2000 lines of APL. That’s not the “small” student project you’re implying, in any language, and in APL that’s quite substantial.
To me professional implies production/real world/paid work, not just an unfinished academic project.
Such poor quality comment.