HNHacker News
TopNewBestAskShowJobs

asQuirreL

306 karma · joined September 1, 2014

Email: $ echo -n "YW1lbm9uOTQgW3NBbFRdIGdtYWlsIFtET1RdIGNvbQ==" | base64 -D

Stack Overflow: http://stackoverflow.com/users/1091208/amnn

Github: https://github.com/amnn

submissionscomments
asQuirreL··on Beeper Mini removed from Google Play?
Sounds like the kind of planned obsolescence that Apple has been [sued for in the past](https://www.theverge.com/2020/3/2/21161271/apple-settlement-...).
asQuirreL··on Beeper Mini removed from Google Play?
IANAL but does this argument not smell like Bundling?

https://en.wikipedia.org/wiki/Bundling_(antitrust_law)

It's not quite the same because Bundling seems to be about setting a price that is too low, so this isn't a legal precedent but it seems like a morally similar argument?

You are saying that you paid Apple for a device, and that entitles you to access to their services (e.g. Apple bundled their services with their device for free).

If this was Apple's main contention with Beeper, then why not allow people to pay a one-off fee to access their services (whatever fraction of the retail price of a device goes towards services)?

I suspect they can't do this because then you would be fully in Bundling territory: that the one-off price you pay to access Apple's services becomes cheaper when bundled with a device.

The whole idea that you paid a one-off fee and that covers your indefinite access to Apple's servers at a continuous cost to them also seems like a flawed model if that's really what the economics of iMessage are. Of course the contention is that the continuous fee to you is the fact that you are locked in and are therefore helping Apple attract other people to their ecosystem.

There is also another argument going round that somehow the issue is that Beeper is charging for their service. I don't buy that, because I pay for Beeper and I don't use their iMessage integration (because I live in the UK so this whole blue bubble green, bubble thing is just not a thing here and we can just enjoy watching it unfold with idle curiosity) and I pay the same as someone who would. I am paying them on a continuous basis because they are running servers that I want access to that bridge to other services I use and want aggregated in one place.

asQuirreL··on What is it like to be a crab?
I'm not sure if this is a serious suggestion or not, but I don't think trying to measure intelligence gives a full picture of consciousness.

I can't know for sure but I also don't believe that if a living being is assessed to be less intelligent, that it feels less or is in some way less conscious.

I guess this all speaks to a troubling line of thought that justifies treating other beings as lesser for being less intelligent. Be kind to each other, and the bats, and the crabs, then let's talk about consciousness.

asQuirreL··on A New Coefficient of Correlation
If we are talking about billions of entries, even of just 32bit integers, we are talking about 4GB of data, your sort is probably going to be IO dominated, not CPU (comparison) dominated. In which case you'd likely use a sorted data structure with a much higher branching factor than 2 (like a B-tree or LSM tree).

Take the B-tree example, with 4KB pages, you can fit 1000 integers in there for a branching factor of 500, and a performance multiplier of just over 3.

asQuirreL··on Mozilla to put ads in Firefox address bar suggestions
I do think the second implication makes sense, if you take out the tenses, i.e.:

If I am willing to entertain then they honestly spell what they're doing and why.

It means that if you know that I am entertaining the idea you can infer from that they were honest.

asQuirreL··on Stanford apologizes after vaccine allocation leaves out medical residents
I've got to be honest, I answered yes to both your rhetorical "are these algorithms?" questions, which I'm guessing was not your intention. It would help if you gave some examples of what is missing in each case (in your eyes) disqualifying them.

With the SQL example:

I don't think a set of rules is disqualified from being called an algorithm if it's implemented using some other tool or process, because we do this all the time: when programming, we split up implementations into functions, or we could have used the standard library's sort function too -- I would still consider it an algorithm no matter how the "sort the results" step ended up being implemented.

If the result is wrong, it is not necessarily because the implementation of SQL's ORDER BY is incorrect (it could be but it's unlikely for a popular SQL implementation), and if you know that the the rules are incorrect then I agree, I definitely wouldn't blame the sorting algorithm (at least initially, although it's possible it's also be wrong).

asQuirreL··on Miranda: A non-strict functional language with polymorphic types (1985) [pdf]
Oxford also taught a few courses in Haskell:

- Functional Programming - Digital Systems - Principals of Programming Languages.

Compilers was primarily in OCaml, and there were several other courses in Scala.

asQuirreL··on The Guardian Pulls Out of Facebook’s Instant Articles and Apple News
There absolutely is a filter bubble, you just aren't the one doing the filtering. Not that I am philosophically opposed to the filtering, but rather the denial of its existence.
asQuirreL··on React Native for Ubuntu
Your app doesn't need to be single threaded. To begin with, the JS that you write is running on a different thread to the app's UI thread, but if you also have blocking work that you want to offload to another thread, that is possible by writing a native module [1, 2]. The story isn't perfect, there are probably some things that you want to be dealt with asynchronously, but could be written in JavaScript, but on this front React Native isn't any less limiting than native.

[1] https://facebook.github.io/react-native/docs/native-modules-...

[2] https://facebook.github.io/react-native/docs/native-modules-...

asQuirreL··on Twitter's Fucked
Recent studies [Nolan 2010] have shown this method to be tricky and dangerous, but effective.

[Nolan 2010]: https://en.wikipedia.org/wiki/Inception

P.S. Sorry... couldn't resist ;)

asQuirreL··on Functional Programming Jargon
As far as I can tell, the definition is accurate. The only thing I would say is that `flatMap` is the name given to the (usual) list monad's bind operation, and is not used for arbitrary monad's binds.
asQuirreL··on Tabs slower than spaces in Firefox
That would be more like

  inoremap <Tab> <Space><Space>
The request was: when I press two spaces, I want a tab character to be inputted. I agree that if you want `n` spaces when the tab key is pressed, you should use `expandtab` and `shiftwidth`.
asQuirreL··on Tabs slower than spaces in Firefox
In vim, adding the following to your .vimrc should do it:

    inoremap <Space><Space> <Tab>
asQuirreL··on Destroy All Ifs – A Perspective from Functional Programming
Clarity is a bit subjective, I think. The difference between:

    CaseSensitive
    CaseInsensitive
Is harder to spot (for me) than between:

    CaseSensitive True
    CaseSensitive False
This is because the bit that is the same is all on one side, and the bit that is difference is all on the other side. Case in point, your data definition has a typo: `CaseInsensative`, which occurs after the `In` shifts it away from the bit it should be the same as in `CaseSensitive`. Every little bit helps.

What's more, while you may be right that at the surface, the two representations are equally performant, what the newtype has that the data declaration does not, is the Prelude's definitions of all the boolean operators. If you wish to perform any more complicated logic with your data declarations treating them as booleans, you must either cast them to booleans (which comes at a runtime cost), or you must replicate the functionality of the Prelude for your custom type (which comes at a development cost).

Your branching logic (which, let us suspend disbelief and say is "not so bad", just for now) may require the combination of multiple such booleans, which in your encoding scheme would each get a different type due to their semantics, then we can't even viably define our custom boolean operators, so are forced to cast everything to booleans.

The point I'm making here is that outwardly, you want the type to reflect the semantics of how its values are used, but inwardly, you want access to its representation in a way that makes it easy to combine (or put another way, depending on who's looking, the semantics of a value changes).

Also, there is nothing stopping you from changing code later to meet changing needs. Using a newtype now doesn't preclude you from ever using a data declaration in the future. Certainly, you will have to change the patterns and constructors used in a couple of places, but that is a matter of minutes: Time you have already spent weighing the future implications of this decision in your mind right now, so this sensation of time saved is a fallacy.

asQuirreL··on Writing custom type systems for Python in Prolog
The variations are in the implementation detail, the type checking algorithm that Kiselyov describes in your link is extensionally equivalent to Algorithm W. OCaml's type checker is slightly different to HM, but only to deal with the type semantics of things that HM was not originally meant to deal with (like mutable references for instance).

The link Kiselyov mentions is between Garbage collection (-ish, really it's more lifetime analysis a la Rust) and when it is appropriate to generalise a free type variable and how they both interact with aliasing. Take the following expression:

    fun (x) let y = x in y
Here's what we expect:

* It has type `forall 'a . 'a -> 'a` (Keeping the universal quantification explicit).

* The value held in `y` outlives the scope of `y`, because it is aliased in `x`.

But the naïve solution results in:

* The type `forall 'a 'b . 'a -> 'b` (Any function of this type is pure sorcery)

* The value of `y` (and `x`) gets deallocated at the end of `y`'s scope.

The solution is that each type variable should keep track of the scope it was introduced in (like de Bruijn indices), and when generalising, we only universally quantify variables at more deeply nested scopes (which corresponds to deallocating unreachable things).

asQuirreL··on Destroy All Ifs – A Perspective from Functional Programming
The article seems to advocate type synonyms like the following:

    type Case = String -> String
    -- ...
    type Announcer = String -> IO String
I would argue that these are actually much worse than not having type synonyms at all.

(String -> String) functions could do anything to your query parameter and text, the type is too coarse, and the inhabitants too opaque for us to reason about them easily. Naming the type suggests the problem is solved without actually having solved it. It is like finding a hole in the ground, and covering it with leaves, so you don't have to look at it anymore. You are literally making a trap for the next person to come this way.

In an ideal world you would be able to use refinements to say that you want any (f :: String -> String) such that `toUpper . f = toUpper` but without such facilities, I think I may just settle for:

    newtype Case = CaseSensitive Bool
Sometimes, your type really does only have two inhabitants.
asQuirreL··on React: Mixins Considered Harmful
Traits and mixins are different. A trait/interface/protocol doesn't generally contain implementation, and when it does, it is based only on other methods in the trait (for things like default implementations), whereas mixins are just fragments of a class implementation with potentially arbitrary dependencies on methods.

So traits document the dependencies that mixins make implicitly.

Traits in typed languages can only cause name clashes if two methods in different traits have the same name and the same type signature. This is immediately obvious, and the compiler will warn you so you can fix it there and then when you try and implement them both for one class. (It also brings into question whether there should be another trait to hold that shared method).

The snowballing complexity that is mentioned stems from all those implicit dependencies: There's no way of knowing what they all could be in a nest of related mixins, whereas the corresponding traits document it and provide a map, of sorts.

asQuirreL··on Google to Train 2 Million Indian Android Developers
Just to clarify, the position of people insinuating that training 2 million Indian people to be Android developers will cause a proliferation of malware: Would your reaction be the same if it were a western country?

If it is, then I would argue that the people writing malware apps are educated at a level beyond the training Google will likely provide.

Full disclosure, I'm an Indian person who has training in Android app development, but don't worry, I'm not yet harbouring any malware-producing urges.

asQuirreL··on Amazon software engineer interview
Perhaps the willingness to prepare indicates the candidate is motivated and the algorithmic knowledge they gain from it forms a solid basis and language in which it is possible to test their problem solving abilities?
asQuirreL··on Mental Models I Find Repeatedly Useful
Ah yes, I see. I guess I was looking for a place where the fact that `Pd1` and `Pd2` were small, but I guess that's not necessary.
asQuirreL··on Mental Models I Find Repeatedly Useful
You are right, they are different questions, but the straw man was not intentional, I thought the original phrasing was ambiguous enough that it could be interpreted in both ways ;)

In other words, it was unclear to me what the answer to the question "Are the assumptions part of the hypothesis?" was. If, as I did, we assume that "yes, they are" then I don't think it follows that the probabilities will both be `1`, because we do not have logical proofs for the claims, the implication could only be true in the model (they are not necessarily entailments).

The waters are muddied further still when the hypothesis itself is phrased as an implication.

EDIT

It also strikes me that for your line of reasoning to hold, it is not sufficient that Pd1 = Pd2 are small, but instead `Pd1 = 0 = Pd2`, in order to justify this line:

    > = Pd1 + P((A1 & A2 & ... & Ak) & H1)
    > = Pd1 + P(A1 & A2 & ... & Ak)
Which is tantamount to saying

    (A1 & A2 & ... & Ak) <-> H1
  & (A1 & A2 & ... & Ak & ... & An) <-> H2
Is it not?

EDIT (2)

Ignore that, it is not tantamount, it is a weaker condition.

asQuirreL··on Mental Models I Find Repeatedly Useful
At least in the terminology I'm used to, of mathematical proof, an assumption is a part of the context under which a thing is proven. So having more assumptions weakens the claim (and there is an associated weakening rule [1]).

In other words, the claim "Assuming Q, I prove P" does not mean (to me) that Q must hold in order for P to hold, but rather that one way to show that P is true is to show that Q is true.

[1]: https://en.wikipedia.org/wiki/Structural_rule

asQuirreL··on Mental Models I Find Repeatedly Useful
Occam's razor, as stated by GP is not about correctness, but tractability. In fact, if you look at it probabilistically, the hypothesis founded on more assumptions is more likely to be correct:

Suppose you have a hypothesis, H, which is based on assumptions A1, A2, ..., Ak. This can be phrased logically as an implication:

    (A1 & A2 & ... & Ak) -> H
Decomposing the implication, we get:

    !A1 | !A2 | ... | !Ak | H
Then

          Pr(!A1 | !A2 | ... | !Ak |  H)
    = 1 - Pr( A1 &  A2 & ... &  Ak & !H)
So, appealing to the conjunction fallacy, assuming that we are adding more assumptions on top, rather than having a greater number of different assumptions, the probability of success actually goes up.
asQuirreL··on May is Earth's hottest on record
I take it then, that your username is ironic?
asQuirreL··on The most alienating thing that happened to me as a female engineer
You are right, it is just democracy at work, but I'm not sure that that is different from a group trying preserve its identity.

The interesting thing is that most people assume that democracy is inclusive, because everybody has a voice, but in this case, the inclusive thing to do would have been to watch something that only one person wanted to watch, to make them as a minority, comfortable, whereas the democratic thing to do is to ignore the opinion of the minority as not relevant to the views of the group.

Where the discussion becomes difficult, I guess, is when the dividing line between majority and minority coincides with that of privileged (PS. I hate what this word has come to mean) and unprivileged.

asQuirreL··on The most alienating thing that happened to me as a female engineer
I feel like it is a diversity issue, albeit not of the usual kind, and it is not exclusive to groups whose identity is strongly linked to gender.

All groups will try and preserve their own identity, because if they don't, they stop existing. I'm merely making an observation here, not condoning the actions of groups. This kind of behaviour may seem harmless in some situations, but then also fuels some of the worst instances of discrimination humanity has seen.

asQuirreL··on Lambda crabs, part 1: A mathematical introduction to lifetimes and regions
Lattices and the associated Galois connections are used quite a bit in the Abstract Interpretation school of program analysis [1].

[1]: https://en.wikipedia.org/wiki/Abstract_interpretation

asQuirreL··on Show HN: 2D field of view demo
This is some interesting work! I was musing about another algorithm to achieve the same effect, as I was reading:

* First render the scene in 3D, from the viewer's position, using a perspective transformation with the right field-of-view to match the "bounding angle".

* Save the resulting Z-buffer into a texture.

* When rendering the 2D, top-down scene, you can consult the Z-buffer (now a texture) to see whether that pixel should be highlighted or not.

I think this is a technique that's already used, but almost complementarily, to calculate shadows from dynamic lights.

asQuirreL··on Null References: The Billion Dollar Mistake – Tony Hoare (2009) [video]
Parent means something closer to pointers (in C++) when they say "reference type". In other words, if a type contains null, then we must always check locally that values of that type are not null before it is safe to use them (or manually maintain contracts).

With option types, we check whether it is empty once, and if it is not, we unwrap it and use it as if it were never nullable. Any function that uses the unwrapped value downstream is oblivious to the fact.

asQuirreL··on Double-ended vector – is it useful?
Yes, there are, but in my opinion, for it to be a circular buffer, it should wrap the end of the data back round to the front when the end of the queue reaches the end of the buffer.

Inserting 4 into:

    [x, x, x, 1, 2, 3]
Produces:

    [4, x, x, 1, 2, 3]
In a circular buffer, and:

    [x, 1, 2, 3, 4, x]
In the proposed "double-ended vector". The technique is different, the amortized complexity is also different. I think therefore, it warrants a different name, to avoid confusion.
← PreviousPage 2 of 4Next →