Hacker Newsnew | past | comments | ask | show | jobs | submit | endgame's commentslogin

The command to load a program in TI BASIC was actually "OLD <DEVICE>". Probably because they already had "NEW".

https://www.ninerpedia.org/wiki/TI-99/4A_system_usage#Loadin...


The reason it had the OLD command is because the original version of BASIC, Dartmouth BASIC, had the OLD command.

Microsoft BASICS didn't have it.


My 40 year old memories are indeed faulty. Thanks for the correction!

FWIW, I probably confused it with Commodore Basic, since part of me wanted to put a ",1" at the end of the load command.


Yes. Here's a 2014 BBC article about that:

https://www.bbc.com/news/uk-politics-26487418

The article quotes one Mr Richard Mawrey QC:

> "Postal voting on demand, however many safeguards you build into it, is wide open to fraud… on a scale that will make election rigging a possibility and indeed in some areas a probability."

> "Now I know that there is a very strong political desire to keep the present system. What I'm saying is that if you keep the present system, then however many safeguards you create, fraud and serious fraud is inevitably going to continue because that is built into the system."


There are some really clever systems that let you prove that you voted without leaking how you voted.

Unfortunately, explaining them to Joe Q. Public in such a way that he's going to trust your election is a very tough sell, whereas counting paper is a much easier process to explain.

And that's before you begin worrying that the developer of your whizz-bang mathematically-provable voting system is a) going to win the bid to build it for the government, b) implements it correctly, and c) isn't subverted while doing so.


I have had this discussion many times before, with people smarter than me, and I have not yet reached a counter argument to the idea that if you can only prove that you voted (and not couple each vote to a voter), how can you prove that innumerable votes were added to the record, or that your vote is correct?

You can either couple every vote to a voter and risk oppressive monitoring of votes at scale or coercion at micro level, OR you can have decoupled voting proving that your vote was counted, but not have convincing proof that your vote or anyone else's are accurate.

Please prove me wrong because I would love it if it was possible.

Edit: Booth/paper-voting solves this by:

* linearly scaling cost of multi-party verification of identity at time of voting

* your vote being anonymous and being decoupled from you at time of deposit

* you trust the system at scale since each step in the chain-of-custody has many-eyes-verification

* vote amount is grouped by location so vote insertion can't happen at scale without coordinating with each involved polling place to fudge each of their numbers

* you can't insert into one area without having a random 100k population increase in a polling place overnight


You could try reading the Wikipedia article on the end to end voter veritable system called Prêt à Voter. https://en.wikipedia.org/wiki/Pr%C3%AAt_%C3%A0_Voter It's not that hard to grok how it works because there is no complicated math involved.

It allows any voter to verify their vote was accurately recorded in the reported total. The usual argument against is you need a lot of people to verify, and most won't. That's probably true when everyone is confident in the outcome, but I'm not so sure it works be true if there was a wiff of fraud in the air.

> how can you prove that innumerable votes were added to the record, or that your vote is correct?

In Australia it's easy to prove no votes to the record because everyone on the rolls must vote, or they get fined. Ergo total votes must equal the number of people on the roll minus the number fined. As for "your vote was counted" - read the Wikipedia article. These systems do prove that, while keeping your ballot secret.


> You could try reading the Wikipedia article on the end to end voter veritable system called Prêt à Voter. https://en.wikipedia.org/wiki/Pr%C3%AAt_%C3%A0_Voter It's not that hard to grok how it works because there is no complicated math involved.

> It allows any voter to verify their vote was accurately recorded in the reported total. The usual argument against is you need a lot of people to verify, and most won't. That's probably true when everyone is confident in the outcome, but I'm not so sure it works be true if there was a wiff of fraud in the air.

There are a number of application details which wildly alters whether it's workable or not, where workable leans fairly close to current scalable cost, in which case the added benefit is minimal.

> In Australia it's easy to prove no votes to the record because everyone on the rolls must vote, or they get fined. Ergo total votes must equal the number of people on the roll minus the number fined. As for "your vote was counted" - read the Wikipedia article. These systems do prove that, while keeping your ballot secret.

Yes, but only by using as much verification as paper ballot casting, which is already provably robust and even more verifiable due to decentralization.

Skimmed these:

https://www.usenix.org/legacy/event/sec05/tech/full_papers/k...

https://www.researchgate.net/publication/277296393_Pret_a_vo...


> Yes, but only by using as much verification as paper ballot casting

I'm not sure what you are getting at here. A voter can not verify their vote in the current paper systems. Using these systems they can.

There are two kinds of attacks: typically classes as retail and wholesale. Retail attacks happen at the front end: stuffing ballot boxes, coercion, vote buying. As the effort involved roughly corresponds to the number of votes altered changing a large enough volume of votes to alter the outcome will be detectable using robust social systems, which boils down to teams of people watching each other.

Wholesale attacks happen when the vote is processed after they have been cast. An example is altering vote counting machine to lie about the votes counted. As they can systemically alter large numbers of votes they can be very difficult to detect even using statistical megtods. They are impossible to pull off when everything is done manually as teams watching teams still works, and you have to corrupt a lot of people. But when you introduce automation and machinery they voting system becomes vulnerable to this sort of manipulation.

Yes, "just continue to do everything manually using pencil and paper" does mostly eliminate wholesale attacks. But the reality is we are ditching pencil and paper for more automated processes. A famous example is a Diablo voting machine in some USA state, failed before regurgitating it's vote count (the "Volusia Error"). A man with a screw driver duely arrived, modified things, and handed over what he said was the correct vote count.

We are automating voting with voting machines and vote tabulators for good reasons. They are easier to use, particularly for the disabled, they are faster, they are cheaper than redundant teams of people, and they more accurate than manual methods. They are already arrived, and their use will only grow over time. Pleas like yours to "just use paper" are having little effect on their inceasing adoption.

The other option is to insist these machines and systems are end to end cryptographically verifable. That makes wholesale attacks these automated systems facilitate detectable. Currently we are deploying these systems without such safeguards. IMO this is insanity.


> I'm not sure what you are getting at here. A voter can not verify their vote in the current paper systems.

In the current paper systems you don't have to, as you know what you put on it before it got anonymized and counted as one vote by the teams watched by teams.

> Using these systems they can.

In theory, yes. In practice, barely. If it was easy/practical it would be intrinsically susceptible to coercion.

In general, I agree with everything you write except for this paragraph:

> We are automating voting with voting machines and vote tabulators for good reasons. They are easier to use, particularly for the disabled, they are faster, they are cheaper than redundant teams of people, and they more accurate than manual methods. They are already arrived, and their use will only grow over time. Pleas like yours to "just use paper" are having little effect on their inceasing adoption.

The only "good" reason would be cost, but I wouldn't agree that it's a worthy trade-off. They could be easier to use, but it seems generally to be prone to UI issues making it unclear who/what you're voting for.

I'm sure their use will grow over time, but it won't be for any reasons that are good for democracy.


> In the current paper systems you don't have to,

True. But the "secret ballot in a polling booth using paper" systems are disappearing. 32% of Australian votes aren't done that way now.

> In theory, yes. In practice, barely. If it was easy/practical it would be intrinsically susceptible to coercion.

It can be reduced to scanning a QR code in an app. It is a bit of a mystery to me why you think that isn't easy, practical or is susceptible to coercion.


> It can be reduced to scanning a QR code in an app. It is a bit of a mystery to me why you think that isn't easy, practical or is susceptible to coercion.

Because "scanning a QR code in an app" would lead to:

1) integrity loss, ie reduction of peers in the secret sharing concept.

and/or

2) privacy loss, ie vote coercion, "show me you voted for our dear leader or something bad happens".

You can either confirm your encrypted ballot is present, OR you can decrypt it before being cast, in which case it can't be cast anymore. Unless I'm missing something they're mutually exclusive. The entire premise of the mix net is not being able to verify what you voted for, only that your vote is there, right?


The best-designed website on the internet.

https://hey.paris/posts/appleid/

This guy purchased a gift card which turned out to be dodgy, and Apple locked his entire account. So there's definitely some kind of shenanigans possible with the current supply chain.


Which other VPN providers support the range of payment methods that Mullvad does?


That's not an argument when the Mozilla Foundation makes it structurally impossible to fund Firefox.


Of course they aren't. If they were actually helping kids, they would be going after algorithmic feeds in general and the most predatory platforms like Roblox (especially given its recent scandals), doing something about kids being exposed to gambling advertising, etc.

The bill was put up for public comment for less than one business day before being rammed through Parliament. Australia is just sending out one of the horsemen of the infocalypse so that other countries have an excuse to follow suit. Like how our "Assistance And Access" Act was a test run of the UK's "snooper's charter".

This law will just lead to:

1. kids pretending to be adults so they sneak through these filters

2. platforms winding back their (meagre) child safety efforts since "children are banned anyway"

3. everyone being forced to prove their age via e.g. uploading ID (which will inevitably get leaked)


>going after algorithmic feeds

This is such an older person take. Users really like Algorithmic feeds and see the removal of such a feature to be platform destroying. Cronological feeds are still easy to game and abuse.

>predatory platforms like Roblox

What makes roblox a predatory platform and what would you change to make it not a predatory platform? To me Roblox is a predatory platform because of the age group of people not because of the platform design.


> kids pretending to be adults so they sneak through these filters

The real question is: how hard does it make it for them to pretend to be adults? We just need it to be hard enough that most kids won't do it.

> platforms winding back their (meagre) child safety efforts since "children are banned anyway"

If the law forces the platforms to properly ban children, I don't see how they can do that. If you're thinking that the platforms will just say "it's illegal for children to join, so we don't have to do anything because they shouldn't come in the first place", then I don't think the law is made like this.

> everyone being forced to prove their age via e.g. uploading ID (which will inevitably get leaked)

Some countries have been working on privacy-preserving age verification. I find it's a lot better than uploading an ID.


> We just need it to be hard enough that most kids won't do it.

Silly though that sounds, it might work. Because it's social pressure from other kids to be online that drives many kids into being constantly on Instagram and Snapchat. If you're not online, you don't know what's going on. The big social networks monetize FOMO.

If a sizable fraction of kids aren't on social media, that's not where it's happening any more. The pressure goes away. Or goes elsewhere.


Validating your comment.

Freakonomics did a podcast about what you are describing.

https://freakonomics.com/podcast/are-you-caught-in-a-social-...


Kids pretending to be adults know they are doing something wrong. They are likely to practice acting like adults, don't pressure each other to join, and are harder for predators to find.


> algorithmic feeds in general

Do you only use /new of HN...?


So it's the reader monad, then? ;-)


Yes.


Can you explain for those of us less familiar with Haskell (and monads in general)?


A reader is just an interface that allows you to build up a computation that will eventually take an environment as a parameter and return a value.

Here's the magic:

    newtype Reader env a = Reader { runReader :: env -> a }
    
    ask = Reader $ \x -> x
    
    instance Functor (Reader env) where
      fmap f (Reader g) = Reader $ \x -> f (g x)
    
    instance Applicative (Reader env) where
      pure x = Reader (\_ -> x)
      ff <*> fx = Reader $ \x -> (runReader ff x) (runReader fx x)
    
    instance Monad (Reader env) where
      (Reader f) >>= g = Reader $ \x -> runReader (g (f x)) x
That Monad instance might be the scariest bit if you're unfamiliar with Haskell. The (>>=) function takes a Monad (here a Reader) and a continuation to call on it's contents. It then threads the environment through both.

Might be used like this:

    calc :: Reader String Int
    calc = do
      input <- ask
      pure $ length input
    
    test :: Int
    test = runReader calc "Test"
    -- returns: 4
Not sure how this compares to Zig!

https://stackoverflow.com/questions/14178889/what-is-the-pur...

Edit: Added Applicative instance so code runs on modern Haskell. Please critique! Also added example.


Here's a minimal python translation of the important bits:

    class Reader:
        def __init__(self, func):
            self.run = func
        def pure(x):
            return Reader(lambda _: x)
        def bind(self, f):
            return Reader(lambda env: f(self.run(env)).run(env))

    ask = Reader(lambda env: env)

    def calc():
        return ask.bind(lambda input_str:
            Reader.pure(len(input_str)))

    test = calc().run("test")
    print(test)
Admittedly this is a bit unwieldy in Python. Haskell's `do` notation desugars to repeated binds (and therefore requires something to be a Monad), and does a lot of handiwork.

    -- this:
    calc :: Reader String Int
    calc = do
      input <- ask
      pure $ length input

    -- translates to:
    calc' :: Reader String Int
    calc' = ask >>= (\input -> pure $ length input)


A Monad is a _super_ generic interface that can be implemented for a whole bunch of structures/types. When people talk about "monads", they are usually referring to a specific instance. In this case, the Reader monad is a specific instance that is roughly equivalent to functions that take an argument of a particular type and return a result of any type. That is, any function that looks like this (r -> a) where `r` is fixed to some type, and `a` can be anything.

Functions of that form can actually implement the Monad interface, and can make use of Haskells syntax support for them.

One common use-case for the reader monad pattern is to ship around an interface type (say, a struct with a bunch of functions or other data in it). So, what people are saying here is that passing around a the `Io` type as a function argument is just the "reader monad" pattern in Haskell.

And, if you hand-wave a bit, this is actually how Haskell's IO is implemented. There is a RealWorld type, which with a bit of hand waving, seems to pretty much be your `Io` type.

Now, the details of passing around that RealWorld type is hidden in Haskell behind the IO type, So, you don't see the `RealWorld` argument passed into the `putStrLn` function. Instead, the `putStrLn` function is of type `String -> IO ()`. But you can, think of `IO ()` as being equivalent to `RealWorld -> ()`, and if you substitute that in you see the `String -> RealWorld -> ()` type that is similar to how it appears you are doing it in Zig.

So, you can see that Zig's Io type is not the reader monad, but the pattern of having functions take it as an argument is.

Hopefully that helps.

---

Due to Haskell's laziness, IO isn't actually the reader monad, but actually more closely related to the state monad, but in a strict language that wouldn't be required.


I see I’ve been beaten to the punch, but I’ll post my try anyway.

Your comment about IO handled by an external system In response to a comment about the more general concept of a monad is what they are, somewhat abruptly referring to in the above two comments.

The IO monad in Haskell is somewhat ‘magical’ in that it encapsulates a particular monad instance that encodes computational actions which Haskell defers to an external system to execute. Haskell chose to encode this using a monadic structure.

To be a bit more particular:

The Reader monad is the Haskell Monad instance for what can generically be called an ‘environment’ monad. It is the pattern of using monadic structure to encapsulate the idea of a calling context and then taking functions that do not take a Context variable and using the encapsulating Monad to provide the context for usage within that function that needs it.

Based on your streams in the new system I don’t see a monad, mostly because the Reader instance would basically pipe the IO parameter through functions for you and Zig requires explicit passage of the IO (unless you set a global variable as IO but that’s not a monad, that’s just global state) to each function that uses it.

From my perspective Zig’s IO looks to be more akin to a passed effect token outside the type system ‘proper’ that remains compile time checked by special case.


Reader monads have been used to implement dependency injection in Haskell and Scala libraries. A monad in general is the ability to compose two functions that have pure arguments and return values that encode some effect... in this case the effect is simply to pass along some read only environment.

Based on my understanding of above, passing an environment as a parameter is not the Reader monad, in fact passing the parameter explicitly through chains of function calls is what the Reader monad intends to avoid in typed, pure functional programming.


Reader monad is a fancy way of saying ‘have the ability to read some constant value throughout the computation’. So here they mean the io value that is passed between functions.


Well I don't think that fits at all. In Zig, an Io instance is an interface, passed as a parameter. You can draw some connections between what Zig is doing and what Haskell is doing but it's not a monad. It's plain old interfaces and parameters, just like Allocator.


Passing an interface as a parameter is a monad. (Io -> _) is an instance of Monad in Haskell.

Haskell just has syntax to make using (any) monad much nicer. In this case, it let's you elide the `Io` parameter in the syntax if you are just going to be passing the same Io to a bunch of other functions. But it still is there.


And for comparison, here's Haskell's (or rather Bluefin's) equivalent of Zig's `Io` parameter:

https://hackage-content.haskell.org/package/bluefin/docs/Blu...


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.


Is it necessary that a monad "builds up a computation and then runs"? In fact it's very hard for a monad to do that because the type of bind is

    (>>=) :: m a -> (a -> m b) -> m b
so you can really only make progress if you first build a bit (`m a`), then run it (to get `a`) then build the next bit (applying `a` to `a -> m b`), then run that. So "building" and "running" must necessarily be interleaved. It's an odd myth that "Haskell's IO purely builds an impure computation to run".


Are you saying "monad" is a synonym of "interface"?


Not a synonym, but `Monad` is one of the commonly used interfaces in Haskell (not the only one).


OK I think I understand now, thank you. My takeaways:

1. Yes, Zig is doing basically the same thing as Haskell

2. No, it's not a monad in Zig because it's an imperative language.


It still is a monad. It's just Zig doesn't have language support for monads, so it's less ergonomic.

Just as modular addition over ints in Zig forms a group, even if Zig has no notion of groups. It's just a property of the construct.

Laziness has nothing to do with it.

What that means practically for Zig, I'm unsure.


Monads do not need to build up a computation. The identity functor is a monad.


Let's see if I can do it without going too far off the deep end. I think your description of the _IO type_ as "a description of how to carry out I/O that is performed by a separate system" is quite fair. But that is a property of the IO type, not of monads. A monad in programming is often thought of as a type constructor M (that takes and returns a type), along with some functions that satisfy certain conditions (called the "monad laws").

The `IO` type is a type constructor of one argument (a type), and returns a type: we say that it has kind `Type -> Type`, using the word "kind" to mean something like "the 'type' of a type". (I would also think of the Zig function `std.ArrayList` as a type constructor, in case that's correct and useful to you.) `IO String` is the type of a potentially side-effecting computation that produces a `String`, which can be fed to other `IO`-using functions. `readLine` is an example of a value that has this type.

The Haskell function arrow `(->)` is also a type constructor, but of two arguments. If you provide `(->)` with two types `a` and `b`, you get the type of functions from `a` to `b`:

`(->)` has kind `Type -> Type -> Type`.

`(->) Char` has kind `Type -> Type`.

`(->) Char Bool` has kind `Type`. It is more often written `Char -> Bool`. `isUpper` is an example of a value that has this type.

The partially-applied type constructor `(->) r`, read as the "type constructor for functions that accept `r`", is of the same kind as `IO`: `Type -> Type`. It also turns out that you can implement the functions required by the monad interface for `(->) r` in a way that satisfies the necessary conditions to call it a monad, and this is often called the "reader monad". Using the monad interface with this type constructor results in code that "automatically" passes a value to the first argument of functions being used in the computation. This sometimes gets used to pass around a configuration structure between a number of functions, without having to write that plumbing by hand. Using the monad interface with the `IO` type results in the construction of larger side-effecting computations. There are many other monads, and the payoff of naming the "monad" concept in a language like Haskell is that you can write functions which work over values in _any_ monad, regardless of which specific one it is.

I tried to keep this brief-ish but I wasn't sure which parts needed explanation, and I didn't want to pull on all the threads and make a giant essay that nobody will read. I hope it's useful to you. If you want clarification, please let me know.


This is pretty concise, but is still really technical. That aside, I think the actual bone of contention is that Zig’s IO is not a Reader-esque structure. The talks and articles I’ve read indicate that function needing the IO ‘context’ must be passed said context as an argument. Excepting using a global variable to make it available everywhere, but as I said in a sibling comment, that’s just global state not a monad.

In a manner of speaking, Zig created the IO monad without the monad (which is basically just an effect token disconnected from the type system). Zig’s new mechanism take a large chunk of ‘side-effects’ and encapsulates them in a distinct and unique interface. This allows for a similar segregation of ‘pure’ and ‘side-effecting’ computations that logically unlined Haskell’s usage of IO. Zig however lacks the language/type system level support for syntactically and semantically using IO as an inescapable Monad instance. So, while the side effects are segregated via the IO parameter ‘token’ requirement they are still computed as with all Zig code. Finally, because Zig’s IO is not a special case of Monad there is no restriction on taking IO requiring results of a function and using them as ‘pure’ values.


A series of functions all passing the same `io: IO` value around exhibit exactly the behavior of the reader monad.


I've used Nix for at least seven years, and I firmly believe that the language is a large part of the problem. Yes, the Nix language is "just another lazily-evaluated pure FP language in the ML tradition" and "it's like a lazily-evaluated JSON", but it has several large footguns. The biggest one is that spaces are use to separate elements in list literals as well as for function application. The second is the lack of a usable type system, in the sense that the programmer cannot assert the types of values in a useful way. Instead, you have to rely on comments and convention to know what a function's arguments are.

These two design warts also interact with each other really badly: If you try to put a function application into a list and forget to enclose it in parentheses, you instead insert the function as one element in the list and its arguments as successive elements. The usual result is "expected an X but got a function" error in some completely unrelated part of the code.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: