IIRC that talk of about using indices (u32) to represent data in an array. That is orthogonal to representing that information in the type system since you can just type the index
HN user
doyougnu
Some shameless self-promotion
I think this is exactly right. I've been thinking of "this time" as similar to the advent of digital spreadsheets. Spreadsheets existed for thousands of years but spreadsheet programs transformed spreadsheet work that took hours or weeks into seconds. You still had to know what you were doing, and if you knew what you were doing you were easily 10x faster than those that didn't.
I think we are in a similar situation with code generation now, then only difference in my mind is that LLMs come with a massive platform risk. Who's to say that one day anthropic decides my company is too much of a competitor to use their tool (like they've already done with openai) or what if they decide that instead of pulling their product from my use they just make it generate worse code, or even insert malicious payloads. A dependence on these tools is wildly more risky than dependency on a word processor or a spreadsheet program. It reminds me of the arguments around net neutrality and I cannot fathom how people building on top of, and with, these tools do not see the mountain of risks around them.
I'm honestly shocked by this having been an Ars reader for over ten years. I miss the days when they would publish super in-depth articles on computing. Since the Conde Nast acquisition I basically only go to ars for Beth Mole's coverage which is still top notch. Other than that I've found that the Verge fulfills the need that I used to get from Ars. I also support the Verge as a paid subscriber and cannot recommend them enough.
My recommendation: find and cultivate vision, then view the $JOB not as separate from _your_ work towards _your_ vision, but part of it. Its the part that funds you enough to continue to progress on your own plan.
Here's how I think of it: If I were a painter, I would paint, explore and experiment in my free time because its what I want to do. Maybe, as a painter, my vision is to improve the state of the art of some kind of dye or brush or canvas and that is my vision. But! That does not mean that I cannot be commissioned to work on a mural or put on a retainer for a museum or something else. The only difference is that in the latter you are being explicitly payed by a patron to produce something they want. And furthermore I need that work, I work for myself but still need projects to bring in money to do the work I care about.
I view my software dev as the same thing. I have a vision of where I want to be, what I want to do, and how I want to contribute to advance the state of the art of the things I care about. I do not care, and am unconcerned about the corporate needs of the thing I care about, its for me and for people like me. My $JOB is just one part of that larger goal and the path I walk towards that goal. Its an important part, sure, and I show up and give a good faith effort and my expert opinion, but its not the part that enriches me as much as my personal stuff. The distinction is that the $JOB is not separate, its a necessary and important part of my plan to execute on my vision.
Once you have vision I think you'll find its much easier to find similar people who want to work on the same things you want to work on. And I think you'll find it much easier to tolerate capitalist minutiae because you will reduce the things you need from $JOB.
I've interfaced with some AI generated code and after several examples of finding subtle and yet very wrong bugs I now find that I digest code that I suspect coming from AI (or an AI loving coworker) with much much more scrutiny than I used to. I've frankly lost trust in any kind of care for quality or due diligence from some coworkers.
I see how the use of AI is useful, but I feel that the practitioners of AI-as-coding-agent are running away from the real work. How can you tell me about the system you say you have created if you don't have the patience to make it or think about it deeply in the first place?
Couldn't have said it better myself. But IIUC Andrew stated that its not a monad because it does not build up a computation and then run. Rather, its as if every function runs a `runIO#` or `runReader` every time the io parameter is used.
Agreed. the Haskeller in me screams "You've just implemented the IO monad without language support".
Not a game dev. Besides profiling, I would create game scenarios that exercise certain parts of the game engine.
For example, I would create a game fight scenario where the player has infinite health and the enemy just attacks super fast at some settable rate. That way you could monitor whats happening in extreme abnormal conditions with the hypothesis that if the game works in extreme conditions then it will work in normal conditions.
Another example. If you have random encounters like in old school JRPGs then I would create a scenario where a fight happens per step of the player, the fight loads, then the enemy immediately dies, rinse wash and repeat. That should allow you to asses how the game performs after 100s of fights quickly.
The idea here is to create tests that improve your signal to noise ratio. So you create a scenario that will create a large signal so that then you can more easily diagnose the performance issues.
I haven't dabbled in rust since 2018, but if rust has managed to be as complicated as C++ while being a fraction of the age then I would think that would be some kind of macabre achievement in its own right.
I still like Olin Shiver's take on this: https://www.ccs.neu.edu/home/shivers/papers/why-teach-pl.pdf
Does every usage site have to change? You would alter fibonacci to be:
fibonacci :: (MonadLogger m, MonadState (Int, Int, Int) m) => m Int
fibonacci ...
and now of course all callers must support MonadLogger. But instead of using the MonadLogger (or any mtl constraint directly) you should just be constructing an abstraction boundary with a type class synonym: class (MonadLogger m, MonadState s m) => MyMonads s m
and now you change fibonacci: fibonacci :: MyMonads (Int, Int, Int) m => m Int
fibonacci ...
And now if you need to add a monad or add Eq or whatever you just have to change your type class synonym rather than every function. Its not a problem with the language its just programing with modularity in mind, even in the type system.Great! If you could open an issue and perhaps lay out what you would like to see I would be more than happy to add a chapter like this. This book should serve the community and I think you've described a good gap that the book has which we could close with such a chapter.
I think that is a fair assessment of that chapter. The goal of the chapter was to take a project that has never done any kind of optimization and to show an optimization engineering pass. Basically one has to be sure the implementation doesn't have any obvious easy to fix leaks before considering a different algorithm or something like that.
So I would argue that the real message of that chapter is demonstrating, step-by-step the methods used to find the memory leaks: info-table profiling and biographical/retainer profiling and ticky-ticky profiling.
A chapter dedicated to understanding laziness is indeed doable, but my target audience is Haskellers that have already read through LYAH, Real-World Haskell and perhaps UPenn's CIS 194 class; each of which cover laziness and so I want to focus on things that should be more widely used or known, such as info table profiling, eventlog or the one-shot monad trick.
But that doesn't mean that laziness doesn't come up! For example, its impossible to demonstrate using (or defining) unboxed or unlifted types without discussing laziness. The same goes for using GHC.Exts and explaining the difference between Data.Map and Data.Map.Strict.
Author here! I figured it was only a matter of time before this showed up on HN after the haskell foundation announced we had moved it the HF org. If you have any recommendations then by all means please open an issue, but bear in mind that the book is still very much a work in progress. And most chapters are just todos at the moment.
My goal is to have a handbook that consolidates and demystifies optimizing GHC Haskell because I think this resource is sorely missing in the Haskell community. So that includes reading and understanding Core, Stg, and Cmm as well as understanding the tools that already exist for GHC Haskell but are under documented in addition to the real advanced features, like altering the RunTimeRep your data types to control their behavior at runtime. Needless to say there is a lot to do :)
Hi coauthor here!
Work has been steady the master project plan is tracked in this ticket: https://gitlab.haskell.org/ghc/ghc/-/issues/17957
Almost all the recent work has been performed by Dominik Peteler (@mmhat) during Google summer of code, which John supervised. We've primarily been focused on landing !8341[0] which makes huge strides in Core w.r.t. modularity (see https://gitlab.haskell.org/ghc/ghc/-/issues/21872), but are on hold until schedules agree and some vacations end.
So the modularity project is far from dead. In fact Sylvain and I are planning on returning to it after we upstream the new Javascript backend (slated for 9.6, see MR!9133[1], tracking ticket[2]) hopefully this week.
PS: That patch is actually a good example of a gnarly lung transplant for GHC's Core IR (and done by a new contributor!).
[0] https://gitlab.haskell.org/ghc/ghc/-/merge_requests/8341
[1] https://gitlab.haskell.org/ghc/ghc/-/merge_requests/9133
Yea and the best part was that installing NixOS was dead easy. I followed Graham Christensen's instructions[1] and had nix create a personalized image with the latest linux kernel and some other stuff. Then I just flashed and booted from that image after partitioning. Honestly it was dead simple and its so hard to go back to the ad-hoc system config style a la Arch linux and other distros.
I'm probably a lost cause now because I think I'm going to convert my entire raspberry pi cluster to NixOS from ubuntu.
battery life with that laptop was always better on the mac, but I regularly got 4-6 hours on that machine for years, first with Arch linux, and then with NixOS.
Suspend hasn't failed me yet but I run suspend+hibernate.
Trackpad seems good to me but my setup is not trackpad heavy. In fact I have a hotkey binding in xmonad that disables the track pad because everything I do is keyboard based including my browser. So I find I rarely need to use the mouse and it just gets in my way.
Battery depends on usage, with nothing (nothing is emacs daemon, wifi on, bluetooth on, xmonad and syncthing running, I don't use a desktop environment) running my battery reports a discharge rate of 5-6W, with normal usage (firefox and chrome open, slack and spotify open) the battery discharge is ~9-10W which is easily 6 hours, of course when I'm compiling GHC with all cores firing away this shoots up to ~30W and battery tanks to 1-2 hours but I can't really blame the machine for that :)
I recently bought a framework laptop for a daily driver when I'm not on my desktop. For context I was running NixOS on an old 2014 macbook air, and I work on the glasgow haskell compiler in my day job so I do a lot of CPU heavy tasks.
I've got to say, as long as these things are being produced I'll never go back. They are just too good and I cannot recommend them highly enough. One of the things that didn't occur to me before I bought it was that _because_ of the modular design I can switch the side the power port is on. That may not seem like much but it was a revelation the first time I sat on the couch and thought "huh I really wish this was over on that side....wait a minute!".
I've also had absolutely no problems with NixOS on my machine, even my apple earbuds easily connect via bluetooth, something that I never quite got working on my macbook.
10/10 This is damn close to my dream laptop and I'm excited a new version is on the way.
I can confirm a lot of what has already been said. I've used spacemacs since 2017, have contributed to it, and have written several private layers for it, such as a custom org layer.
But I switch to Doom emacs literally two weeks ago and I'm never going back. I find doom to be much faster not just startup time but in general responsiveness (one major exception: hitting SPC and waiting for key binding tips to show seems to be much slower in doom than spacemacs). Other than that I found doom to be much easier to configure and much more configurable.
The major selling point for me was that in doom emacs there is much much less ceremony in wrapping a new package in a module, and more importantly it is _easier_ to reuse documentation for those packages because most packages provide configuration examples using `use-package` anyway. My only hangup was less documentation around writing custom modules which took me about a day to figure out (I would advise to just read some of the source code or mimic a module that doom ships with).
YMMV, but if you feel like you've attained a certain level of emacs maturity, I would 100% recommend trying it out. Be prepared that some modules, like the haskell module, don't ship with a lot of keybindings so you'll have to set those up yourself.
Clojure doesn't solve the expression problem and the expression problem tends to be trivial in dynamically typed languages.
Strictly speaking the expression problem is only defined for _static_ type systems because its concerned with _static_ type safety and extensions without recompilation.
I completely agree with this. That anyone defends the current employee based health care system in the US is insane to me. The perverse incentives rife in such a system alone should eliminate it in any serious discussion as a viable way to provide healthcare to people.
So much this. I just moved to Germany and the difference in civil servants and general infrastructure is palpable compared to the US