HNHacker News
TopNewBestAskShowJobs

zenhack

684 karma · joined June 20, 2017

[ my public key: https://keybase.io/isd; my proof: https://keybase.io/isd/sigs/sp25K1JliIwzg06OIG9xoMjX6G7YxK3taKIPr-hp2MI ]
submissionscomments
zenhack··on Monads for functional programming (1995) [pdf]
More or less, yeah. Most of the language-aware optimization in ghc happens in an intermediate form that still carries the types, and then ultimately it spits out code that just has side effects as a result of evaluation like every other language.

The code you sketch out above is basically the Writer Monad, which exists in the libraries, and does see use, but it's not IO -- as I mentioned above the semantics of IO don't entirely just fall out of the monadic structure.

But I find the computed-imperative-program description lends itself to thinking about IO values as values in a way that thinking about them as type system goop to tame side effects doesn't; for example, the program:

    import Data.List (intersperse)
    import Control.Concurrent (threadDelay)

    main = sequence_ $ intersperse (threadDelay 1000000) (map print [1..])
will print out the natural numbers, one per second until you kill it. It works by constructing a (lazily evaluated) list of actions to perform, which alternately print out a number or wait for one second. sequence_ has type [IO a] -> IO (), and it just performs each action in the list in sequence (its type is actually a bit more general than this, but..).

This kind of code is really weird to think about from the "tamed side-effects" model, but very natural from the "computing a script" model.

zenhack··on Monads for functional programming (1995) [pdf]
I think you're right in that ghc's actual implementation is something like that, but it is a bit lacking in describing the semantics. To see why, imagine functions:

getLine :: RealWorld -> (String, RealWorld)

putLine :: RealWorld -> String -> RealWorld

And some code like:

    Let (line, w1) = getLine  w0
        w2 = putLine w1 line
        w3 = putLine w2 "other stuff"
        w4 = putLine w3 line
     ...
Now, imagine an optimization compiler for some reason decides it would be better to recompute `line`, rather than hang on to the value in the interim. It would be well within its rights to do so, because referential transparency guarantees that this is safe.

IIRC ghc essentially "plays dumb" and just never duplicates a computation (which is not typically a desirable optimization at this level, though register allocators will sometimes do it). But it's arguably a hack.

A better metaphor is to think of values of type IO a as fragments of a script in some other (imperative) language. The Haskell program merely computes the script, and the runtime then takes care of actually executing it. In this sense, effects in Haskell are not "side" -- they are first class citizens. What order the fragments of the imperative program are computed in (or how many times) is independent of the text of the final program.

In very early versions of Haskell, main had a type roughly like [Response] -> [Request]; you computed a list of things for the runtime to do, as a function of the results of its (hopefully) previous commands. This kinda works, but it's easy to deadlock by creating a circular data dependency. What the Monad structure does for you is avoid that problem, by making it impossible to depend on a future value.

It's also worth pointing out that all of this is specific to IO; understanding monads in general are neither necessary nor sufficient to understand Haskell's IO.

zenhack··on Subscription Hell
> Take my colleague Connie Loizos’ article from yesterday reporting on a new venture fund. The text itself is about 3.5 kilobytes uncompressed, but the total payload of the page if nothing is cached is more than 10 MB, or more than 3000x the data usage of the actual text itself. This pattern has become so common that it has been called the website obesity crisis. Yet, all of our research shows people want high-definition images with their stories, instant loading of articles on the site, and interactivity. Those features have to be paid somehow, begetting us the advertising and subscription models we see today.

It was kindof upsetting to read this after having switched the article into Firefox's reader mode, because the page was completely unusable.

If you want to talk about consumers' wallets not existing in a vacuum: if your 3.5 KB article is sending me 10 megs of crap, then your mobile users' carriers are charging them more than the advertizers are paying you.

There are some real challenges in figuring out how to fund journalism, but if bandwidth is one of them you're doing something very wrong.

zenhack··on Please Stop Using Adblock (But Not Why You Think)
Mostly automation -- you don't have to actually craft the list. It will just spot stuff it thinks it should be blocking and do so. And if you need to correct it (uncommon in my experience) the UI for doing so is right there next to the address bar. Also, it's capable of just blocking cookies for some sites, which is nice when they're hosting common J's libs/fonts or something, and blocking them outright would break the page.
zenhack··on Twitter urges users to change passwords after computer 'glitch'
In particular, the point is to make it so that the thing you store can't actually be used to authenticate -- only to verify. So if you're doing it right, the client can't just send the hash, because that wouldn't actually authenticate them.
zenhack··on A History of APL in 50 Functions
It has an input method that lets you type the non ASCII characters more easily. The default uses the super key (windows key) like alt uses alt, bit there's also a mode that allows you to prefix things with ., So e.g. to get rho you type .r, and to get an actual . you type .., which I find more ergonomic. And you can launch the repl from inside emacs as well. I'm mostly a vim user myself, and have been using it with spacemacs for a more familiar experience.
zenhack··on Implementing and Understanding Type Classes (2014)
Not one of those languages has a construct equivalent to Haskell's type classes.
zenhack··on Blloc – minimalist smartphone
The layout is also broken on Firefox mobile for Android (not a good impression for a website for an Android phone...). The text on the first slide runs off the screen, the second slide is just blank? And the slide with tech specs has the text all jumbled together and overlapping.
zenhack··on Parsing JSON is a Minefield
What you're proposing sounds like cbor and/or messagepack (which are virtually identical in their design), or argdata[1].

I agree it's a pretty solid spot in the design space.

[1]: https://github.com/NuxiNL/argdata

zenhack··on New tools for open source maintainers
Realistically if you've got commits in a public git repo, your email address is public no matter how they got there.
zenhack··on Facebook to change user terms, limiting effect of EU privacy law
They'd also have to stop being based in Europe (they're officially headquartered in Ireland, because tax evasion), and (here's the kicker): stop doing business with all of Europe. Even if they had to say screw it and not do any targeting of their adds at all, it really wouldn't make any business sense for them to take their ball and go home.
zenhack··on Python 3.7: Introducing Data Classes
In this context it doesn't really matter that it's the "default", just that it's supported by the distro maintainers, and so receiving security updates regardless of what the PSF supports.
zenhack··on Python 3.7: Introducing Data Classes
It will probably be a fair bit longer than that before 2.7 stops being relevant. 2.7 is still the default system Python on a lot of Linux distros, which will be in vendor support for longer. It doesn't really matter if the fixes are coming from the PSF or someone else - nice thing about Foss.

RHEL/CentOS 6 is still reasonably widely used, and the system Python there is 2.6.

zenhack··on Why SQLite Does Not Use Git
Ah, That was likely my issue then.
zenhack··on Why SQLite Does Not Use Git
How is your experience of its performance? The last time I tried it I found it made everything unusably slow; disabling that one plugin made an absurd difference in the responsiveness of the machine.
zenhack··on Why SQLite Does Not Use Git
I feel like most of the trouble developers have with Git is pretty shallow, and it's a shame. It's not a tool I would want to get non-programmers to use (which may be a problem if you've got design folks on your team as well), but the model should be pretty learnable (in principle) to anyone who can manage to hobble their way through an intro data structures course.

For folks like me, who spent their evenings in high-school screwing around with obscure linux distros and have been scouring badly written man pages trying to fix their computer for half their life, the little stuff is forgivable, and a lot of the big stuff is pretty good. But it's a shame how many inessential hurdles there are. See also:

https://git-man-page-generator.lokaltog.net/

Biggest piece of advice for not losing data: learn about git-reflog and git-reset before doing anything that modifies history. Nothing is destroyed, even by "scary" operations like rebase, so it's always possible to recover something, but you need to know how to find stuff.

I do some contract work for a university, where we have lots of student interns going through. We use GitHub, and we rarely rebase or cherry-pick, basically because while I could spend a bunch of time trying to teach git to new interns that will be gone in 4 months, It seems like a more efficient use of time to just occasionally put up with a messy history.

zenhack··on Gradual Programming
Yeah, that's an actually reasonable argument (I don't buy it either, but it's coherent enough). But I honestly think most of the time people aren't making that argument, they're just complaining about the typed languages they know -- more often than not Java.
zenhack··on Gradual Programming
Off the top of my head:

* type inference

* message passing concurrency

zenhack··on Gradual Programming
I am in general deeply skeptical of gradual typing, partially from my own underwhelming experiences with MyPy, and partially because 99% of the time when I hear someone advocating for them, they (1) take as given that dynamic typing makes for more productivity (which does not reflect my own experience), and therefore don't try to justify the claim at all, and (2) they say what gradually types give you is not having to annotate things up front. Types have not required manual annotations since at least 1978 (the original hindley-milner type system which, I will note, while not new, is still more recent than prolog).

TFA does all of the above, plus a parenthetical saying "inference is addressed in the next section" -- and then does not actually address inference later in the post.

I'd much rather have type inference than optional typing.

zenhack··on Proposal: Non-cooperative goroutine preemption
The go compiler (already) inserts yields in a bunch of places that aren't IO or explicit synchronization points. And it's hard to predict the exact locations they'll be because much of it happens after some optimizations have been made. It is very much already attempting to look preemptive, which is why the authors didn't use the term coroutine for the language feature -- it's an implementation detail.

This proposal is about fixing some of the edge cases where the current implementation doesn't do what the interface is supposed to. It outlines another, simpler approach which just has the compiler add more yields, but apparently the performance impact of that is too high. But it's just a question of perf & implementation complexity, not semantics.

zenhack··on Ask HN: Does HN respect the GDPR?
The thing is, the EU doesn't have sovereignty outside of Europe. If I actually have presence in the EU, or do business with the EU, that's one thing. But they can't tell some rando with a blog living in Boston to delete comments any more than North Korea can pass a law banning making fun of Kim Jong Un in Berlin. They can huff and puff, but at the end of the day they just don't have the authority.
zenhack··on Guide to Slack import and export tools
Yeah, and there's a reason some places have laws against bugging offices. One key thing is that everyone should be clear on what's recorded and what's not, and "if it's written down" at least has the virtue of relative simplicity. Probably if it's not supposed to be fair game for later investigation it shouldn't be logged at all.

I think part of the trouble is that we spend too much time at work for most people to actually be productive the whole time -- if you buy the notion that it's reasonable for people to be at work to work, and they shouldn't be socializing whathaveyou, then logging everything seems more reasonable than if you recognize that no one can actually be a drone 40/hr a week, then the surveillance starts to look like de facto surveillance of stuff other than the job, which is more worrying.

I am in the privileged position of doing freelance work, on my own machine, mostly remote. As such, if I'm using a client's communication systems it is essentially guaranteed to be work related, so having it logged doesn't bother me; if I'm not working I'm using something else. But being monitored for half your waking hours five days a week feels much more onerous.

I suspect some of a this is tension with reasonable expectations of levels of monitoring from when less of our communication was via the network.

zenhack··on Eve: Programming designed for humans
There's a lot more physical movement involved in the end/ctrl+backspace method, even though it's fewer keystrokes.

The big thing with Vim's modal editing is that it allows you to have keyboard shortcuts involving keys that aren't way off in the boonies. Some examples:

* / or ? to search for text

* dd to delete the current line

* Stuff like ciw or ci" will delete a word or the contents of a double-quoted string, and drop you into insert mode. I use this one constantly.

When prompted, people try to come up with really crazy complex things, but frankly the bigger thing is just being able to actually reach things.

If I tried to use shortcuts in other editors to the extent that I do in vim, my hands would constantly be in pain. This is why I never got into emacs, though I've seen some folks be terrifyingly fast with it as well.

zenhack··on Eve: Programming designed for humans
Yeah, I've seen a fair bit literate code that is awkwardly structured to satisfy ordering needed by the underlying language. It works better in languages that don't care about the order of declarations, of which there are many, but usually there's something at the top to the effect of "we need to start off with a pile of imports, because compiler."

Haskell will recognize a .lhs extension and do comments by default, using > to prefix lines that are actual code (looks block-quote like).

Frankly I am something of a skeptic of literate programming. In most of the literate source code I've read, the code is clearer than the prose anyway, and having every detail in comments just makes the whys and the high level design harder to find.

My approach is to basically assume the reader is familiar with the language and the key libraries, document the whys, overall design, and the api contracts, and try to pick good variables and write clear code. This is not to say "inline comments are bad," but I find that usually when I find myself writing a lot of comments explaining the details it's because I'm writing a lot of confusing code.

zenhack··on What can we learn from how compilers are designed?
Yeah, multiple dispatch implies more than one argument involved in the dispatch decision at runtime. So that's not the same thing.
zenhack··on What can we learn from how compilers are designed?
Unless it's via some new-fangled C++ feature I haven't heard of yet, I'm pretty sure C++ doesn't have multiple dispatch. Can you elaborate on what you're referring to?
zenhack··on Rust-style resource management in OCaml
You can screw up destructors in exactly the same ways. And it also serves to make sure you close the file at all.

But again hence the value of having the lifetime of the object enforced by the type system.

zenhack··on Rust-style resource management in OCaml
I think pjmpl is referencing apis like this:

   with_file "hello.txt" (fun fd -> (* do stuff *) )

where you've basically created a c++ destructor style api with a lambda.

It's certainly not "verification" in any formal sense, and the type system can't help you there any more than it can in c++.

But this is a perfectly reasonable pattern.

zenhack··on Rust-style resource management in OCaml
Okay, yeah, I should temper that statement. This stuff is super hard to actually study rigorously, and I certainly don't have a reference to support as broad and vague a claim as "tend to perform better."

And of course "perform" is a very muilti-dimentional thing, not a single value.

The truth of the matter is that any generic memory management strategy is going to fall on it's face in certain scenarios; most folks have seen first hand the raii failure mode where some application takes forever just to exit, because it's pointlessly calling god-knows how many destructors.

It's late, and I should generally try to be more clear with myself about what my point is before I post. The thing in there that I think is more salient is, with manual memory management you're opting into control, not magic everything-is-faster-now. I don't think the op was suggesting it, but people often act like using a lower level language is going to always make things faster, ans it just isn't true. Idiomatic, decently performing OCaml is going to make for some very slow Rust.

zenhack··on Rust-style resource management in OCaml
Worth pointing out, the resource management strategy isn't even necessarily a net positive for performance. In typical GC'd languages you have a much richer design space for your memory system. You can move stuff around, you have flexibility as to when you do collection, you often have allocation as a built-in primitive, which means the compiler knows about it and can help optimize.

The end result is that good GC-based memory systems tend to perform better than malloc/free style APIs (with the call to free() possibly being implicit). to get good performance in C/C++/Rust, the programmer needs to be concientious about allocation. You have more control, but also more responsibility. In OCaml, allocation is bumping a pointer -- go nuts.

← PreviousPage 6 of 8Next →