Git reset vs. Git revert - github-cat https://www.pingtech.xyz/article/1549115148-git-reset-vs-git-revert#comment_zone <comment><AUTHOR> I always use a soft reset when I accidentally commit in the wrong order, because I like keeping my history tidy. If the change is live, I always use revert.

On another note, I love how HN can go from complex research papers I struggle to keep up with, to explaining git commands the next day — something I learned within my first month of Git and never had a problem with again. How bipolar.

<comment><USER2> If you commit in the wrong order and want to set it straight, learn to use "git rebase -i" (i.e. --interactive)

"git reset --patch" is useful for unraveling changes that were wrongly combined into a single commit.

<comment><USER3> Interactive rebasing works fine for teasing apart commits as well (maybe slightly clumsier, but c'mon... it's git, it's _supposed_ to be a frustrating UX)

<comment><USER4> Yes... it is, until you realize it's a command line manipulation of a data structure.

Rebase, branching, diff, cherry pick, merging is just manipulating a DAG.

When you're on your own branch it's often easier to think of it as a linked list.

<comment> black-tea Even if you're on your own branch you can easily get a DAG after rebasing or resetting. The reflog keeps track of the history of all refs (ie. branch names) that you change. After you rebase your old commits are still there! It's actually quite hard to remove commits.

Trusting the reflog is key to becoming good at git.

</comment></comment></comment></comment></comment><comment><USER5> The explanation that made me understand git reset the best is "Git Tools – Reset Demystified" from the Pro Git book [0].

Everything has been crystal clear since. I highly recommend it if you use git.

[0] [https://git-scm.com/book/en/v2/Git-Tools-Reset-Demystified](https://git- scm.com/book/en/v2/Git-Tools-Reset-Demystified)

</comment><comment><USER6> I think the main thing is, if you've already pushed to somewhere where others will pull from then use revert. Otherwise, use rebase (or reset+cherry-pick or amend, etc). If you push a patchset that has a patch and also a revert patch for that patch then you're just adding completely unnecessary noise for anyone who is reviewing the patches.

</comment><comment><USER7> The chunk about `git reset --hard` should be prefixed with a big warning label saying "Don't use this unless you know exactly what you're doing". There are very few legitimate reasons to use `git reset --hard <commit>` in the way that the article describes and even fewer if you're working with remote. Now `git reset` (No commit or --hard) can be useful to retry a screwed staging, but that's about it. As to squashing commits... that's a whole different set of problems when you're dealing with auditors and code review requirements and "public" commits.

<comment><USER8> Very few? I find myself having to use it a lot (usually targetting HEAD or HEAD~1), and actually it's kind of handy for clearing out any cruft when switching between project branches. The important thing to know is that it only acts on files that are added to git, and will pass over any that are not.

<comment><USER7> I've used `reset` that way a few times, but pretty much never `reset --hard` Still, this is not something that should be suggested to someone unfamiliar with git. It's just too easy to screw up your codebase.

</comment></comment></comment><comment><USER9> This is a pretty bad article.

In the last example (which is actually the most common case in practice), they give wrong instructions. They should only revert the bad commit, not all the following commits. Reverting everything is impractical and useless, and if you want to do that you may as well use revert (which is still a bad idea).

</comment><comment><USER10> I love how the illustrations are actually the obvious default interface that everyone should be using to edit nodes in a graph. Click "Delete" while the box is around C and D: done. (Or right clicking and choosing "commit a reversion" or whatever.)

</comment><comment><USER11> Why is this linked to the comment section?

<comment><USER12> Who knows, but from those comments:

> Really hard to take anything you say seriously when you use the entire > aplhabet for your hexadecimal SHA1 examples.

Touche.

<comment><USER13> I like those hashes. Why don't we use the entire alphabet. Base64 would be cool.

<comment> black-tea Way harder to remember a hash using base64. Hex is much more manageable and you still only need to remember 4-5 digits usually.

<comment><USER13> If it is about memory, why not generate 4 or so words as the 'visual' hash, which is probably good enough for most teams to use for branching/merging without experiencing clashes.</comment></comment></comment></comment></comment>


Google cardboard  - <AUTHOR> http://www.knoxlabs.com/

<comment><USER2> Just ordered! Can't wait to receive it in the mail

</comment><comment><USER3> Can't wait to try it out</comment>


Uber Opens Its API - <AUTHOR> http://techcrunch.com/2014/08/20/uber-api-part-deux/?ncid=rss&utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+Techcrunch+(TechCrunch) <comment><USER2> Though it's not mentioned in the article, Uber recently partnered with Concur for business travel. Uber now sends all my ride receipts directly Concur, and my expense reports are populated automatically -- it's first-class integration right in the app.

And now Uber is opening their API? IMO, this is a huge deal. Perhaps working with Concur really drove home the sheer size of the corporate travel machine, and the massive opportunities they were missing out on by not participating in its web of partners and exclusive contracts. I know Uber already has VIP (in NYC at least) and is coming out with corporate discounts, but I'm betting we see Uber move a lot more in that direction.

<comment><USER3> Uber has been working on this for a long time. No chance the recent Concur / UberForBusiness integration inspired them to open up their API.

</comment></comment><comment><USER4> _"....to get its service on as many apps as possible, it is launching an affiliate program to offer up free credits to developers who get people using its service."_

If they aren't offering a cash percentage, I don't think they're going to find many takers. I certainly wouldn't integrate a new API in exchange for Uber credits.

Edit: On the affiliate page, it says "Cash rewards coming soon" but it seems rather odd that they wouldn't launch with that. Generally affiliate programs pay money.

<comment><USER5> Currently, they offer $5 credit per signup for US developers. Referring via the uber dashboard gives you $10.

Am I missing a point or why would anyone use it if you don't get cash at the moment, get $5 less, it only works for US and you can't register people via the Api?

</comment></comment><comment><USER6> This could potentially be great news - I've been working on an Uber client app for Firefox OS [1] using the reverse-engineering done by the Uber CLI project [2].

It's pretty a pretty basic implementation at the moment (you can currently book a ride based on an address, and not much else), but allowed me to move to FirefoxOS for my primary phone - Uber being the last 'must-have' app for me that didn't have a webapp version.

Having something official to work with (assuming they don't go down the Twitter route of not allowing anything that replicates the functionality of the main Uber app) would help a lot.

[1] [https://github.com/thomshutt/FFUber](https://github.com/thomshutt/FFUber)

[2] [https://github.com/tals/uber.py](https://github.com/tals/uber.py)

<comment><USER7> You can also use [http://m.uber.com](http://m.uber.com) if you can't download the app onto your smartphone.

<comment><USER6> Whoops, did not realise that existed! Fairly sure it didn't when I first started playing with FirefoxOS, but this is exactly what I need

</comment></comment></comment><comment><USER8> Too bad it is read-only. :( TechCrunch Disrupt is coming up next month and I would have loved writing an Uber client for Google Glass. Having the user login on a desktop or mobile and then using their oauth credentials on a companion Glass app is all doable. They simply don't have any API for requesting a ride, however, once you have the credentials: [https://developer.uber.com/v1/endpoints/](https://developer.uber.com/v1/endpoints/)

They have some deep linking APIs to start their apps on Android, iOS, or a mobile web site - but none of those will work on Glass. I suppose, theoretically, I can make the HTTP requests to their mobile site as if I were a browser and a user tapping the right buttons, but that it is a lot more brittle than having an API. It will break any time they change their web site.

Being able to say, "OK, Glass,""Get me a ride" and the car shows up would be exciting. "OK, Glass" "Show me the cost and time estimate to go to the Design Center" is just a boring advertisement. Right now their API just allows boring advertisements, pretty much.

<comment><USER9> As mentioned in the blog post, that API is built but in whitelist-only mode:

 _What about requesting a ride? Yes, we've implemented that endpoint as well, but because calling it immediately dispatches a real driver in the real world, we're releasing it in a more controlled fashion, starting with a small set of partners. Stay tuned for more on that, and please let us know if you're interested in being added to the whitelist._

</comment></comment><comment><USER10> Their developer pages are here: [https://developer.uber.com/](https://developer.uber.com/)

</comment><comment><USER11> My preference is for apps to just have a directions link, and then the various providers can plug into the central OS maps.

The odd thing is that Uber isn't integrated into the iOS Maps app as a transit provider. So you can't actually use it in that fashion.

<comment><USER12> It actually is integrated, but it might not support your area (the configuration file used to tell the system where it's supported might be out of date).

<comment><USER11> Ah, good point. We are in a bit of a grey area at our current location. We don't really have UberX in this town (Middletown, CT), but we live near to the interstate that a lot of UberX drivers are on going to and from a metro they do support (New Haven, CT). So the app will call us a car, but it's always 15-20 mins for pickup time.

</comment></comment></comment><comment><USER13> Uber launches an affiliate program could have just as easily been the title.

<comment><USER14> To answer the question that I had, how affiliates will get paid - [https://developer.uber.com/earn/](https://developer.uber.com/earn/) says in Uber credits, and "cash rewards coming soon".

</comment></comment><comment><USER15> Being able to access the history is nice; could be useful when combined with data from other sources...

The API appears to be well thought out--except for the epoch timestamps without time zone offsets :-(

<comment><USER16> epoch timestamps don't need timezone offsets. The epoch timestamp is the number of seconds from a specified "zero" time. That number can be translated to a time in any timezone. E.g. right now:

      % date +"%s"; date; date -u
      1408580844
      Wed Aug 20 17:27:24 PDT 2014
      Thu Aug 21 00:27:24 UTC 2014

<comment><USER15> Sure, an epoch timestamp can be translated to any time zone, but what was the original time zone?

Consider these questions: Do I use Uber more often before or after noon? Is this a photo of a sunrise or a of a sunset? How late do I typically go to bed?

In the case of Uber we could try to guess the time zone from the coordinates, but it's not trivial.

</comment></comment></comment><comment><USER17> also, here in denver, most uber drivers are also lyft drivers. i.e. drivers keep both apps running to increase their chances of getting a request.

<comment><USER18> Really? That's marvelous. Is there an app begging to be written here? For the independent driver's needs, not for the supplier (Uber/Lyft etc). An aggregator of ride request feeds.

<comment><USER11> Uber provides the drivers with a locked-down iPhone to get the ride requests, so it's not that simple.

<comment><USER18> Surprised; I thought Uber was some sort of public-access ridesharing thing. If they vet drivers and license them, how is it different from any other cab service?

<comment><USER11> Mainly because they don't actually license them unless the local authorities force them to. They do vet them, in theory.

And to follow-on, the practical difference is that they are a lot less terrible than most existing cab / car services.

<comment><USER19> People have been selling/giving away their Uber accounts too, IIRC.

</comment></comment></comment></comment></comment></comment><comment><USER20> From a technological standpoint, there are many reasons why I feel excited and lucky to be alive during this time in history. But smarter safer transportation, spearheaded by companies like Google and Uber, tops the list.

<comment><USER21> How is Uber safer?

<comment><USER2> It reduces drunk driving.

<comment> k-mcgrady ...taxis already do that.

<comment><USER22> Not really. I use Uber pretty regularly when traveling for a ride home from a night out. It's consistent, reliable, and I don't have to worry about the driver trying to take advantage of the fact that I might be unfamiliar with the area and possibly not in my most aware state :)

If it's cold, dark, whatever outside I can call an Uber via the app and know when they're arriving. I can see how long the expected delay is to plan wrapping things up accordingly.

My experience with Taxi's in most of the major US markets is that coverage is spotty, fares can be variable, credit-card acceptance is hit or miss, and the cars and drivers are generally sub-par.

Comparing taxi's to Uber is like comparing a model rocket to the Space X program.

<comment> k-mcgrady I'm not from the US so my view on taxis might be different. Typically I call a number and they have someone there in 10 minutes. It's rare to be taken advantage of because they know you can make a complaint to the taxi company they work for. As for cash I don't think anyone here minds. If you don't have cash on you the taxi driver will stop at an ATM for you.

I've used Uber once and it was great but from my experience with taxis Uber isn't offering much extra.

</comment></comment></comment></comment></comment></comment><comment><USER23> Uber is a dirty company, don't give them your business.

[http://sanfrancisco.cbslocal.com/2014/08/13/uber- employees-a...](http://sanfrancisco.cbslocal.com/2014/08/13/uber-employees- allegedly-canceled-thousands-of-lyft-rides-fake-requests/)

<comment><USER24> I find this problem really strange to be honest. Lyft guys are capable of solving dispatch issues, so why don't they introduce limits in their ToS? For example 5 cancellations in a row - ban. 25%+ cancellations over a period of time - ban. Or instead of a ban, start charging for cancellations over some threshold. If they set the threshold and the resulting action properly, they should be able to handle the bad behaviour with little loss.

I see this as one of the few social problems that can be solved with technology. Use the tech to make the incentives for this behaviour go away.

<comment><USER4> Agreed. This certainly doesn't excuse Uber's behavior, but as a startup you have to adapt and adjust to whatever issues you are confronted with. When abusive cancellations became a problem, they should have made it either impossible or expensive for the behavior to continue.

</comment></comment></comment><comment><USER25> uber moves pretty fast. I think their speed of innovation is commendable. But 17 billion USD evaluation still seem unjustified to me.

<comment><USER26> I used to pay Uber $300+ a month when I lived in SF. Seems like a bargain compared to WhatsApp or Facebook.</comment></comment>


Internet Pioneer Vint Cerf Tests Positive for Covid-19 - <AUTHOR> https://paleofuture.gizmodo.com/internet-pioneer-vint-cerf-tests-positive-for-covid-19-1842559935 <comment><USER2> So sorry to hear that; praying he gets well, along with all others sickened. Thanks to him and to everyone else who worked on the internet; they're the reason why we can still function and communicate at all.</comment>


The Spark Electron Adds Cellular Data to Your DIY Projects - <AUTHOR> http://techcrunch.com/2015/02/25/the-spark-electron-adds-cellular-data-to-your-diy-projects/

<comment><USER2> Gooooo us! Whispernet for everything!</comment>


Ask HN: What is your favorite chess variant (and why)? - crypto-jeronimo <comment><AUTHOR> my favorite variant is standard chess with en passant banned, because I suck at en passant :)</comment>


How to Migrate Your Blog from Wordpress to Django - <AUTHOR> https://techarena51.com/blog/How-to-migrate-your-Blog-from-Wordpress-to-Django/?utm_source=hackernews <comment><USER2> I have been trying this for sometime, but was not able to do it. Will try your tutorial

<comment><AUTHOR> yup wasn't easy, but mezzanine has included a few tools</comment></comment>


World record: 109 terabits per second over single optical fibre  - <AUTHOR> http://www.geek.com/articles/chips/world-record-109-terabits-per-second-over-single-optical-fibre-2011053/

<comment><USER2> More impressive to me is that the first commercial fiber-optic system worked at 45Mbps.

In 1975.

<comment><USER3> Back 25 years ago I worked for the phone company. I was excited to learn that the way fiber works is essentially to carry multiple channels based on divisions of _color_. Of course, when you stop to think about it, that's precisely analogous to carrying multiple frequencies of radio, or audio (as with a modem). But thinking of this in terms of multiple colors being transmitted simultaneously really brought the point home.

</comment></comment><comment><USER4> OK, but can you really call "one" fiber with "multiple" cores a "single" optical fiber?

All the same, pretty amazing stuff.

The current state of the art in systems which are starting to get deployed now is 100Gb/s per wavelength on a single optical fiber. Each fiber can carry 10's of wavelengths.

These 100G systems can use existing fiber that was run for 10G systems. They exploit more advanced modulation techniques than the old "on-off keying" used in 10G.

Backbone carriers are starting to fill up the so-called "dark fiber" that was over-supplied ~10 years ago. This is creating the demand for 100G and eventually higher.

<comment><USER5> > OK, but can you really call "one" fiber with "multiple" cores a "single" > optical fiber?

Depends on what they actually used.

There are special optical fibers with air holes (google for "photonic crystal fibers"), if they produces such fibers to guide multiple modes independently, you can really call it a single fiber.

If they used separate fibers within a single plastic cladding, you can argue about that.

If they used multiple fibers separate plastic claddings, they probably would have been shouted down at the conference where they presented their results :-)

</comment></comment><comment><USER5> Sadly it doesn't state the length of the first transmission channel. Length multiplied with bit rate is the real figure of merit - and 165km * 102Tb/s is really impressive.

</comment><comment><USER6> Too expensive for my laptop.</comment>


MotionRugs: Visualizing Collective Trends in Space and Time (2018) - <AUTHOR> https://www.ncbi.nlm.nih.gov/pubmed/30136979 <comment><USER2> "QuTiP example: Qubism visualizations" [https://nbviewer.jupyter.org/github/qutip/qutip- notebooks/bl...](https://nbviewer.jupyter.org/github/qutip/qutip- notebooks/blob/master/examples/qubism-and-schmidt-plots.ipynb)

And in my PhD thesis, there is a longer part on using recursive 2d visualizations:

[https://arxiv.org/abs/1412.6796](https://arxiv.org/abs/1412.6796)

3 Visualization of quantum sequences 3.1.3 Visualizing sequences

</comment><comment><USER3> Interesting use of Hilbert curves to flatten 2d images and still retain spatial coherency.

Does anyone have a good resource for how to do this on a hexagon grid?

<comment><USER4> There is the Gosper curve : [http://www.toroidalsnark.net/mkss3-pix/CalderheadJMM2014.pdf](http://www.toroidalsnark.net/mkss3-pix/CalderheadJMM2014.pdf) [https://en.wikipedia.org/wiki/Gosper_curve](https://en.wikipedia.org/wiki/Gosper_curve)

<comment><USER3> Thanks dude!</comment></comment></comment>


The cup-of-coffee pricing fallacy - <AUTHOR> https://blog.gingerlime.com/2020/the-cup-of-coffee-pricing-fallacy/ <comment><USER4> I've always hated it because it makes the assumption that everyone is at the same position in the class hierarchy - I'm poor, the last time I drank a coffee shop coffee was something like 8 years ago and even then it was bought for me by my psychologist, your 'cup of coffee a day' price just sounds extravagant to me.

<comment><USER5> But if you're poor...you're probably also not in the market for a $100/m B2B Saas product.

<comment><USER6> If you're poor you are not a target customer for any non-essential paid for monthly service.

<comment><USER7> A cost of doing business is one of the most essential expenses there is.

<comment><USER8> The absurdity of an "essential price"... essential to what, class?

<comment><USER9> To doing business? Doesn't seem absurd at all. Do you think business should just land in your lap for free without having to spend anything for it? That what seems absurd to me.

<comment><USER8> "business" is just one mode of industrial production, even in a marketplace. So, essential for business, perhaps, but hardly essential in a general sense.

</comment></comment></comment></comment></comment></comment></comment><comment><USER10> I hated this assumption too, but for different reasons.

First, the price for a plain old cup of coffee at Starbucks differs from region to region, but it usually normalizes at around $1.80 (taxes included). Refills are $0.52. While, yes, Starbucks's coffee-based offerings (like lattes) are more expensive, coffee from Starbucks is quite cheap and VERY consistent (and cheaper than at a mom and pop coffee shop).

Second, there is more value from that cup of Starbucks coffee than the coffee itself: the space, the music, the Wi-Fi, etc. Products that make this comparison usually don't offer the same value proposition.

<comment><USER11> > First, the price for a plain old cup of coffee at Starbucks differs from > region to region, but it usually normalizes at around $1.80 (taxes > included). Refills are $0.52.

That sounds really cheap, or what's a 'plain old cup of coffee' \- does Starbucks sell filter coffee over there?

<comment><USER12> Starbucks sells filter coffee in the UK.

<comment><USER11> Oh, so they do. Sorry I've just never been aware of that.

</comment></comment></comment></comment><comment><USER13> I found it hilarious when a LA based startup compared their pricing structure to a 'nice meal' (50-100$)

Not only did it insult my definition of a 'nice meal', but also made me not want to give them any more money for 'nice meals'. A nice meal is 700 calories from healthy sources. An extravagant meal is the price they quote.

Similarly $5 is not the price of a coffee... It's about 30p.

<comment><USER14> I've never spent more than $35 on a meal in my life, and I like to think I've had some mighty good ones!

<comment><USER15> Even in big cities I have trouble spending more than this on a single meal. If I'm covering a date or sharing a bottle with the table that changes obviously, but unless you're going to a suit and tie or otherwise haute kind of place then $50 is absurd.

</comment></comment></comment><comment><USER16> The "cup of coffee" analogy always struck me as though it was asking, "Hey, wouldn't you be willing to pay twice as much for your coffee as you do now?" And, well, no. It also misses the mark for anyone who says, "I'm not paying $100 a month for coffee, that's rediculous, I'll make my own.

Now for those who actually _do_ buy their coffee daily, it still assumes Also,it still asdumes a sort of laziness in personal budgeting. If you keep a personal budget and diligently track luxury extras like buying coffee at many x the price if making your own, and a the other little things, then you're going to be very aware and deliberate about incurring additional expenses of that sort. And so if you position your value-proposition in terms of "only a cup of coffee" instead of the value-add of the service itself, then you're automatically poorly targeting your message to the entire population of people that keep careful budgets.

<comment><USER17> I'm pretty sure there was an article on here just recently about how people who spend money even on dumb things don't do it because they don't budget, but because it provides other particulars of happiness. It stated that human life is complicated and min maxing life financially differs from person to person. So while they may spend $200 on coffee, but may also bike to work daily. Or they just flat out enjoy it and trade money for that enjoyment.

However, the Lionshare of consumers are not rationalizing their purchases like people such as myself often do (I know that comes off as incredibly pretentious, I'm just using myself as an example). I've gotten worse with my money (or better) intentionally so as not to be too cheap and give off the feeling that I'm tight. Normally I'd be that way, but people dislike those kinds of people...like a lot.

Overall just think of it as people paying a tax for something to further continue. It's a tax you don't have to pay, but can freely do so if you choose.

<comment><USER16> You can spend lots of money on dumb things and still budget. But a person who diligently budgets their money will not spend money on dumb things at the expense of debt, lack of proper long term financial planning, etc. Dumb things can fit into a careful budget.

</comment></comment></comment><comment><USER18> On the other hand, most SaaS founders, especially in B2B, are inclined to charge too little for their service. So the coffee analogy can wake you up that $5/mo or $10/mo is an almost ridiculously low price for a piece of software that solves any sort of problem.

It's worth pondering why SaaS founders are so inclined toward underpricing. I think this is because SaaS founders, especially if they are developers, tend to be really frugal in their SaaS and PaaS spending. For example, they'll use things like their DigitalOcean Droplet cost or their GitHub Pro subscription as a point of comparison. They'll think, "Those services are _so_ valuable, and so cheap, so why would anyone buy my thing for more? I certainly wouldn't."

But what they tend to forget or ignore is that, especially in B2B, it's not your buyer's wallet or money at stake. It's your buyer's (or your buyer's department's) allocated budget. And budget allocations for businesses in mid- market and enterprise are always measured in thousands of dollars, and sometimes in millions.

All they care about is spending the money wisely -- that is, appropriately trading money for revenue, for cost reduction, for time savings, for company cultural impact, or, ideally, for all of the above. At that point, pricing too low can be counterproductive: many enterprises will, consciously or subconsciously, worry that your pricing being that low means you are a counterparty risk and thus not even worth hiring as a vendor.

In the B2C space or in the "B2B tools for individual employees" space, to understand your pricing power requires understanding your buyer demographics. If you are selling productivity software to executives, they will think in terms cost relative to their time and the time of their assistants and subordinates. If you are selling hosting software to entrepreneurs, they will want low starting pricing but be OK with pricing that scales quickly with growth. If you are selling a video streaming or premium content service to consumers, they will anchor you against Netflix, Disney+, Hulu, and cable. Selecting your price is a very important part of your strategy and how your service is perceived. Picking the lowest price you can afford at reasonable margins, which is a kind of obvious default, is often a terrible strategy.

</comment><comment><USER19> The problem with "cup-of-coffee pricing" is that if I trust everybody that has a subscription to sell to me, at the end of the month I will be broke.

Too much subscriptions is death by a thousand cuts.

<comment><USER6> Exactly. People who want a service for $5.00/mo aren't viable customers for SaaS

<comment><USER20> They can be if the SaaS is really really simple. I'm imagining stuff like what used to be $25 shareware that the owner now charges $10 a year for.

</comment></comment></comment><comment><USER21> This article frames the cup-of-coffee pricing comparison as: "$100/mo is less than a cup of coffee every day". But I most frequently see the comparison as: "$5/mo means giving up just a cup of coffee once a month".

In this formulation, I think it's a pretty reasonable comparison, since a prospective user doesn't have to sacrifice much (just a semi-luxury item, one day a month) in order to use your service. The author's criticisms don't seem to hold as much purchase (no pun intended) in this context.

I'd be curious to know if others think of cup-of-coffee pricing as $5/mo or $5/day. The only context where I can remember hearing per-day pricing is life insurance or supporting a child in a developing country.

<comment><USER22> $100 a month is less than the amount I spend on coffee, but most people seem to think I have a problem.

<comment><USER21> If you spend this much in coffee shops, I highly recommend you try the Cash app, from Square. If you turn on the "coffee shop boost", you get $1 off of every purchase made at a coffee shop. There's a 30-minute recharge period required between purchases, and a $1.50 minimum purchase.

The sign up process is a little bit of a hassle, but for anyone buying multiple cups a day, it's probably worth it.

If you sign up via an invite code, you get $5 free (and your referrer does too). For anyone who wants it, my referral code is: [https://cash.app/app/HSMSVXP](https://cash.app/app/HSMSVXP), or you can just sign up at [http://cash.app](http://cash.app).

note: I do not work for the company — I just find this perk to be very handy!

</comment></comment></comment><comment><USER23> To me, the coffee price comparison makes your service sound like it's a frivolous and unimportant purchase.

You're better pointing out how much it will cost a business in time and money to solve a problem themselves and compare that to the cost of your product. If you're selling too cheap, the problem probably isn't big enough or important enough.

</comment><comment><USER24> In many instances I would argue relationships in the B2B sale are more important than price. I have both lost and won many deals because of only the relationship.

Just recently a fairly large one we lost had a fantastic ROI, about a 10% ramp time to the competition, and even had the CTO's buy in. But we lost and found out it was bc the VP was neighbors to the other sales rep and he convinced the CTO not to buy from us. From what I can gather from the other folks that were championing for me was mostly untrue FUD was used by this VP, all in an effort to help his buddy. Their cost was supposedly ~30% higher and I usually stomp that product to the ground - because of business cases.

</comment><comment><USER25> Article misses the fallacy of the comparison. If I buy a cup of coffee, I get my end of the bargain immediately* and no further commitment on my part is needed. For most saas offerings though, I'm basically committing to a regular payment in perpetuity. Usually if I stop paying, I not only lose the immediate benefits, but also whatever I have put into the app in the time I used it. Even if it is just storage, if I cancel it, I have to find a way to replace the storage and the access to the storage from my devices.

Committing to a monthly payment is usually not the same as buying X coffees for a month.

*or close to immediately if it is one of those annoying poor over places

<comment><USER26> I think the article did discuss your point, "But [with a cup of coffee] nowhere am I asked to 'subscribe' to anything. I buy it, enjoy it, and that's it. I'm not committed to buy another cup ever again."

Maybe you wanted him to emphasize that particular aspect more.

<comment><USER11> I actually do 'subscribe to coffee' though; I get beans delivered by [https://pactcoffee.com](https://pactcoffee.com) (UK only I think).

I can't recall the keyword for this in the realm of economics, but it's a weird thing to compare 'good value' across sectors. I do it quite often, wonder why I think X is such a rip-off when I won't even blink at Y - <USER2> for that reason I've never had a problem with coffee-currencied pricing.

At least for consumables (coffee, groceries, SaaS in the sense that even if you don't consume a quota you consume a timeframe) I think there is value to be had in comparing their relative value, but only secondarily to comparison against something of the same type of course.

<comment><USER27> Most people can afford a thing for price x easily. Had they never balked at price x, they would pay 20 times x and that is entirely different number.

Meaning, it is not just about comparing value of goods. It is much more about keeping strategy that is easy to remember and execute, but allows you to keep savings.

</comment></comment></comment></comment><comment><USER28> When I lived in NYC, a local coffee-place-slash-home-design-store offered a subscription, whereby if you used it almost every day, you'd be getting significant discount on your artisanal latte. I think they went on to try and create some kind of loyalty rewards app, but for a while, this concept was real. [https://www.10best.com/destinations/new-york/new- york/articl...](https://www.10best.com/destinations/new-york/new- york/articles/fair-folks-a-goat-more-than-meets-the-name/)

</comment><comment><USER6> I'm the person who has been quoted.

The person whom I addressed that was going to run a business selling access to a _commenting feature_. [https://news.ycombinator.com/item?id=22209411](https://news.ycombinator.com/item?id=22209411)

The competition for that feature is free comments via Facebook so anyone who does not want to spend money has that ability. The other set of "competitors" is accessed for free via open source software that one can install.

As soon as the person signs up a first client, he or she would have to provide the service for some period of time. Just shutting it down won't be an option. Any and all businesses are a pain in the ass to operate.

Say that in order for this "business" to be viable in the eyes of the person running it ( not profitable, just viable ) it would need to eick out $500/mo in revenue.

To do that at $5.00/mo he would need to get 100 customers. That's a very tall order because the competition is _free_ and price sensitive customers are going to go to a free service (facebook) or they are going to go to whatever service that shows up that will underprice the OP.

There's however _another_ group of potential customers. They are people who for some reason need a problem of commenting solved and are willing to pay for it. Not a lot. But a some reasonable amount of money. What's reasonable? Well, a dinner for 2 in major cities is the USA is going to run you about $120. People who go out in those cities 4-10 times a month are the same people who have a daily Starbucks/La Colombe/Joe's Coffee/Pete's Coffee habit. They _could_ make the coffee at home for $0.25 a cup just like they could make a dinner at home for $3/per person. Instead they choose to spend money not on the cheapest option but on option that simply solves their problem. They demonstrate it by buying Starbucks coffee and going out to dinner twice or three times a week.

It is much easier to find 5 of people who spend $100/mo on Starbucks who need to have commenting problem solved and convince them to spend $100/mo on it than to find 100 people who would spend $5/mo who think that spending $100/mo on solving their problem is too much. Why? Because the second group has already demonstrated that $100/mo is an expense they are willing to take.

<comment><USER29> > Well, a dinner for 2 in major cities is the USA is going to run you about > $120.

Not for the vast majority of people.

<comment><USER6> [https://www.zagat.com/b/48.56-what-can-you-get-for-nycs- aver...](https://www.zagat.com/b/48.56-what-can-you-get-for-nycs-average-meal- cost)

That's from 2013.

The vast majority of people are not potential customers for a small SaaS startup charging money for "it would be nice to have" service.

</comment></comment></comment><comment><USER30> It's funny because I've often had the opposite thought. Cafes should sell subscriptions. The margin on a single cup of coffee is humongous because there's so much overhead in running a cafe and such variable demand. That seems like a perfect business case for a subscription model.

<comment><USER31> Sounds like a great way to end up with a cafe full of freelancers working on their macbooks.

<comment><USER32> That's a good "problem" to have if you price and market it correctly

<comment><USER33> Right, but then you don't really have a coffee shop anymore.

I disagree with the posters above who say there's a 90% markup on the coffee. What you're buying at Starbucks isn't a coffee, but a coffee _plus_ the right to sit at a table and use the wifi for an hour or two. And as OP points out, at the moment, this is pay-per-use: when I need a place to sit down for a bit, whether in my own city or some other city, or when I need a table to sit and chat with someone that's not in either of our homes, I buy the right to take a seat for $4. They even give me a cup of coffee to go along with it.

Making it a subscription would completely change the way I related to such a business. I mean yeah, I wouldn't have to drink coffee just to sit down. But I'd be thinking each month -- am I getting a good value out of this subscription? I'd be sitting a lot more in the shop than I normally would; which would mean more regular income for the owner, but less space for random people in a strange town who want to have a nice place to sit for an hour.

$4 for a one-off, no commitment, pay-as-you-go service with instant gratification (buy the coffee, take a seat) seems like a pretty nice deal to me; and it makes cities nicer places to be than if you had to have a subscription.

<comment><USER20> Out here Starbucks has been building/opening a ton of new places lately, some of which are replacing old ones. The new ones are strictly outdoor seating.

<comment> frosted-flakes How does that work in winter?

</comment></comment></comment></comment></comment></comment><comment><USER34> The author misunderstands people. Nobody is doing the math or spending effort to otherwise rationalize spending decisions this way. It's an emotional plea - and we're all dumb so it works. Same reason all retailers are always having a 'sale'. We really are that stupid.

</comment><comment><USER35> Coffee is cheap. Anytime you go to a coffee shop and purchase coffee, you're paying for everything that isn't coffee: lease, labor, worker's comp, milk, sugar, taxes, syrup, whipped cream, cups, lids, sleeves, straws, equipment maintenance, etc.

<comment><USER36> That's not really what the article is about. Getting coffee is low risk. Apps are high risk. There are so many garbage apps that aren't worth a single cent and choosing the right one is very difficult.

<comment><USER35> And there are many "coffees" that people are overpaying for because the coffee itself is so cheap. I think we're in agreement here.

</comment></comment></comment><comment><USER37> There is little need for opinions here - just A/B test and see what works better.

<comment><USER38> It's hard to test in some cases when there's high variance, and customers seeing regular price changes comes with its own downsides.

<comment><USER37> This isn't A/B testing a price change, it's just an associated message about N cups of coffee.

</comment></comment></comment><comment><USER39> The cup-of-coffee pricing does make sense. It's not for everyone, there are folks who drink coffee at least 5x a week by paying for it. Those sort of statements are targeted to them. However the fundamental flaw is that in that thinking is with software, someone might just show up and offer free software, we don't see the same with coffee. What makes B2C software hard to sell today is the free apps. Consumer's are now price sensitive to useful apps and most companies think they can make it with ads.

</comment><comment><USER40> One more thing: things seems cheaper when priced over smaller intervals. For some reason, 50 cents per day sounds cheaper than $15 per month which sounds cheaper than $180 per year.

I don't know why. It's a bit like how everything ends in .99. even when you know it's being used on you, it still works.

</comment><comment><USER41> I drink a pot of coffee a day, which works out to around $.03 per cup. Pretty cheap for that vice.

I know that Starbucks tastes better than my drip machine, but I don't really care. Coffee is coffee to me, java junkie that I am.

<comment><USER42> Just get an espresso machine (the real ones, no capsules) and a bean grinder. Coffee from freshly-ground beans tastes way better than Starbucks, is still $.03 per cup and takes only a few seconds to make with an electric grinder.

Moka pots work too and are cheaper (though espresso machines are real cheap at least here in Europe) but the coffee isn't as creamy and it takes a few minutes to boil (even though it needs no attention). With a large moka pot it's easier to make large quantities though (but I hate stale coffee so I favor espresso machines). Still better than drip.

If you're really into coffee get a superautomatic machine. Best coffee I've ever had, instant and with zero effort.

<comment><USER43> "A few seconds to make" is a slight exaggeration no? I had such a grinder/Gaggia set-up and it took time and effort. Producing good espresso at home without very expensive automated machines, is a commitment.

There's a lot of fiddly cleaning involved - the grinder has to be cleaned meticulously after use as do the various bits of the espresso machine. The finely ground coffee is very sensitive to static so tends to jump/attach itself to white t-shirts and plastic kitchenware - more cleaning. All this cleaning is required even if you just want to make one espresso - <USER3> later uses will have a nasty taint.

There's a lot of experimentation required to produce a decent espresso with crema from such a set-up. Depending on the beans, their age, the weather, etc., the fineness for grinding and how tightly you packed the portafilter would vary. On good days I was getting 3 out of 4 but that still meant 1 in 4 (or more) were dreck.

<comment><USER42> That wasn't my experience. The grinder and espresso machines I used just needed rinsing between cups and a quick scrub at the end, plus cleaning the water tank once a week (depending on water quality, tap water is gross).

Moka pots are a pain to clean though, but you can buy a huge one to produce a large quantity.

</comment></comment></comment></comment><comment><USER44> Of course this author has to virtue signal about how _he_ would never buy a Starbucks coffee

> First off, I would personally never buy a cup of coffee at Starbucks. But I > understand why some people would.

He'll only take his Arch Linux Pinebook (ok, I just assumed that) into his "local roaster"

> The cup-of-coffee-fallacy becomes much more obvious when it comes to > subscription services. I might buy a cup of coffee from my local roaster, > and would happily buy many cups, some beans, and snacks on a regular basis.</comment>


Offer HN: Your app, my design, two markets - <AUTHOR>

Here's the deal.
If you are a single hacker founder and have an app with a market or service that I am also interested in working on, I will design the website, the logo and the user interface for free. Plus we will get to market it not only in the US but also in Latin America.
Interested? Drop me a line at nico @ nico .im <comment><USER2> What's in it for you, if I may politely ask?

<comment><USER3> I'm considering of doing the same thing. My main motivation is to meet interesting people working on interesting stuff.

</comment></comment><comment><USER4> I just shot you out an email

</comment><comment><USER5> sent you an email.</comment>


Giant tortoises show surprising cognitive powers - <AUTHOR> https://www.nature.com/articles/d41586-019-03655-5 <comment><USER2> When I worked in Central Illinois recently, the home my wife and I rented bordered a field where young cows were raised. The small cows seemed to play some sort of game, running around each other like run after the leader. We thought they were playing. Later my wife found stuff on the web about cows being given beach balls to play with and with each other. Uncomfortable truth for people who selfishly help environmentally destroy our planet with their meat addictions? I would say yes.

My small Meyers Parrot similarly plays games, remembers things for months but does eventually seem to forget things he has learned. His neocortex is probably only one square inch.

My personal belief is that in life in the universe (with about 400 billion galaxies _times_ about 100 billion stars per galaxy) is wide spread, if rare. I think there is also some pressure for life to develop different types of intelligence based on their biology and environment.

Anyway, I am in strong agreement with the people here saying that it is difficult to recognize non-human intelligence as intelligence.

<comment><USER3> > some pressure for life to develop different types of intelligence based on > their biology and environment.

I always wonder what was the pressure for humans to develop recursive language, and the cultural explosion about 70,000 years ago.

And in the millions of years before that, the pressure to rapidly dwvelop larger brains. Other animals didn't seem to do that (though, we probanly haven't tracked the development of other animals brain-sizes over such time spans as assiduously as our own).

<comment><USER4> The pressure may have been having hands. It's amazing all the things we can do with our hands.

<comment><USER3> Interesting. Could have opened possibilies for intelligence to have utility. BTW parrots are quite dextrous with their feet and tongue.

<comment><USER4> Unfortunately for parrots, they cannot evolve larger brains without giving up flying. I suspect that birds in general have very optimized brains because of the weight constraints.

<comment><USER3> Though flightlessness is an option: emu, penguin, dodo, even a parrot (New Zealand _Kakapo_ ).

<comment><USER4> Unsurprisingly, those evolved where they had fewer predators they needed to fly away from.

</comment></comment></comment></comment></comment></comment></comment><comment><USER5> Any farm kid can tell you that animals are smart, especially if they've gotten into a battle of wits with a goat.

As Mark Twain said (and I am paraphrasing), "the only distinction between man and the lesser animals is that the lesser animals don't sit around and talk about what makes them different from us."

<comment><USER4> > the lesser animals is that the lesser animals don't sit around and talk > about what makes them different from us.

Yes, they do. I won't let my cat near the computer, as she'll use it to log onto catnet and plot the cataclysm with the other cats. I've also caught her leafing through my electronics parts catalogs. I'm not sure how worried I should be.

<comment><USER6> Just use this: [https://bitboost.com/pawsense/](https://bitboost.com/pawsense/)

(PawSense is a software utility that helps protect your computer from cats.)

</comment></comment></comment><comment><USER7> Teaching about language in a university setting, we often talk about various forms of evidence for language-like communication among animals.

As I tell students, I would bet that within our lifetimes, as research continues and our instrumentation becomes better at detecting non-human communication means, we'll finally be able to detect and decode 'language' in a non-human animal which is sophisticated and rich enough as to be impossible to handwave away.

But what I keep to myself is that this kind of discovery, and the cross- species conversations it would prompt, has the potential to change the course of the dialogue on animal rights and what it means to be 'human'. But I suspect it will wind up being largely buried outside of certain academic and spiritual communities, mostly because I don't think parts of our society could handle learning the bovine words for 'slaughterhouse' or 'mourning'.

<comment><USER8> Christina Hunger has the ability to ask her dog questions and it goes to press a button that represents the idea it wants to reply with. That button plays an English word through a speaker for Christina. She's a speech pathologist on Instagram and has a website for it. The dog learns word association in the same way babies do.

Those videos are on Instagram, not buried. I'm fairly sure any breakthroughs will make it to a Planet Earth documentary and we'll feel sad about it for a while then go buy beef from the shops anyway.

<comment><USER9> that's neat. i talk to my dog all the time. she (a rescue) came to me already knowing "do you wanna go out?" but had a really hard time teaching me when she had anxiety diarrhea and needed to go out. i really needed a button for that (she's mostly over it now though).

</comment></comment></comment><comment><USER10> There is still some evolutionary chauvinism when it comes to assumptions of animal intelligence as "distance from humanity" as other counterexamples prove them wrong already.

Reptilian brain crap which seems based on superficial shape when we really should know better now given evidence sitting in front of us.

It doesn't really hold. Sheep are infamously too dumb to live unassisted perhaps owing to overbreeding for docility.

Meanwhile cephalopods are capable of opening jars and get up to mischief like getting out of their tank and shorting out light fixtures when bored and I have observed hermit crabs transmitting behavior socially ("punching" instead of pinching with their larger claw) and figuring out how to rotate an improperly secured lid on its axis.

</comment><comment><USER11> They're still reptiles though. They can't show signs of empathy or affection like many mammals.

Most reptile training is pretty basic, and this experiment fits into those expectations:

[https://m.youtube.com/watch?v=NnwIlM6SmiQ](https://m.youtube.com/watch?v=NnwIlM6SmiQ)

<comment><USER12> They do show signs of affection and empathy, but it's different, a lot more nuanced and subtle.

If you're comparing them to dogs, which are pack animals where those skills are critical, it's not fair. They project their feelings.

Introverted animals have a lot in common with reptiles.

</comment></comment><comment><USER13> Why surprising? If they move so slow they must have some other advantage that enables them to persist.

Humans really need to get over themselves as the only species that possesses intelligence.

</comment><comment><USER14> I keep getting surprised at the inability (refusal) of humans that we are not the only intelligent (and emotional) life form on this planet. It is extremely annoying.

<comment><USER15> I think it's a subconscious act of self-preservation. Truly accepting the sentience of animals would be conferring upon them a much more expansive (and expensive) set of rights, which in turn would make the our society seem all the more immoral through how we treat other species. Too much cognitive dissonance.

<comment><USER16> They are sentient, alright. But quite dumb. So we grow and eat them.

<comment><USER17> Define: dumb.

<comment><USER18> We have been able to teach them to do trivial tricks on demand, but we can't teach them to be productive members of society. We haven't even been able to teach a single other species to do factory work, which is the simplest work imaginable for humans.

<comment><USER19> Does this count?

The Baboon That Controlled a Railway for 9 Years - [https://www.youtube.com/watch?v=OpoLkMcQh24](https://www.youtube.com/watch?v=OpoLkMcQh24)

Although not factory work this Baboon was a productive member of society being paid in alcohol and a small wage.

<comment><USER18> It wasn't clear but did the Baboon ever do the work without James being there? I agree it is impressive, but if the monkey couldn't man the position on its own, like doing the work and only getting the beer and pay once a week and no other rewards, then I don't think it counts.

<comment><USER19> I'm not sure it matters if whether James was there or not so long as the Baboon was capable of performing the tasks without instruction from James which multiple sources appear to imply.

[https://en.wikipedia.org/wiki/Jack_(baboon)](https://en.wikipedia.org/wiki/Jack_\(baboon\))

[https://web.archive.org/web/20160125001616/http://www.earthf...](https://web.archive.org/web/20160125001616/http://www.earthfoot.org/lit_zone/signalmn.htm)

<comment><USER16> I think this is a pretty generous interpretation given how old and random the sources are.</comment></comment></comment></comment></comment></comment></comment></comment></comment>


Where Have All the Men Without College Degrees Gone? - <AUTHOR> https://www.theatlantic.com/education/archive/2019/03/decline-men-without-degrees-labor-market/584479/ <comment><USER2> The article doesn't seem to draw any conclusions?

It also doesn't mention a major contributor, which is high paying jobs without degrees.</comment>


C# and F# approaches to illegal states - <AUTHOR> http://enterprisecraftsmanship.com/2015/09/28/c-and-f-approaches-to-illegal-states/ <comment><USER4> I think folks are lost in the weeds of criticizing the specifics of the example code and not paying attention to the larger design message - <USER2> being F# provides language constructs that make it easier to avoid allowing illegal states, and the type system will help detect that during compilation.

Yes it is a contrived example, yes you can write "better" C#, but this is a short example for illustrative purposes.

I bet if somebody wrote a blog post about Djikstra's letter "GOTO considered harmful" 45+ years ago, attempting to illustrate it with more examples, it would have collected similar comments: nothing wrong with GOTO, I can use it correctly; that example of spaghetti GOTO code is poor and not idiomatic; the example code is too simple and nobody would write it that way; yes it takes discipline to use GOTO without ill effects but nobody would accidentally/maliciously subvert my GOTO hierarchy; etc. Meanwhile, the original point about structuring code using different techniques to help avoid problems (and avoid GOTO) would be lost.

It's like people are overly defensive about language features (or lack thereof) as if writing extra boilerplate and not letting the compiler help is a badge of honor.

EDIT: clarity

<comment><USER5> I think that is highly questionable. Sum Types are a different approach with some advantages and some disadvantages over inheritance. Nothing more and nothing less. They really shine if you have clearly defined types that seldom change. On the other hand, discriminated unions make it absurdly complicated to defend against some errors that are almost comically easy to avoid by using a standard OO approach:

      class Range {
          public int From {get;}
          public int To {get;}
          public Range(int from, int to) {
              Assert(from <= to);
              From = from; To = to;
          }
      }

<comment><USER4> Nobody says you have to use sum types to solve all problems in the design domain - and as kvb points out, F# does have OO functionality too.

Your proposed problem might be better solved with the Option type and a simple guard to return None if out of range.

>comically easy to avoid using a standard OO approach

This is an ironic statement given that your code, as written, is circumvented by subclassing Range and side-stepping its constructor. I suppose you actually meant "sealed class"... but we're getting off in the weeds again, missing the fundamental point of the post.

<comment><USER5> > This is an ironic statement given that your code, as written, is > circumvented by subclassing Range and side-stepping its constructor.

You are the second one who says this. I must admit that I do not understand how this would be possible. The properties are not virtual, and not writable for anything but the base constructor. To my knowledge, it's impossible avoid the base classes constructor by subclassing. I'm pretty sure you can actually circumvent the assert, but you would have to use the heavy weapons in the reflection API.

        class Range
        {
            public int From { get; }
            public int To { get; }
            public Range(int from, int to)
            {
                Assert(from <= to);
                From = from; To = to;
            }
        }

        class LolRange : Range
        {
            public LolRange() : base(0,1)
            {
                From = 1; To = 0;
            }
        }

        Error CS0200 Property or indexer 'Program.Range.From' cannot be assigned to -- it is read only
        Error CS0200 Property or indexer 'Program.Range.To' cannot be assigned to -- it is read only

</comment></comment></comment></comment><comment><USER5> I don't get it. It is perfectly valid to use immutability and the Type system to enforce those invariants in c#.

        abstract class User {
            public string Name { get; }
            abstract bool IsActive { get; }

            public User(string name) {
                this.Name = name;
            }
        }

        class ActiveUser : User {
            public ActiveUser(string name) : base(name) { }
            private ICollection<Subscription> _subscriptions = new List<Subscription>()
            public IEnumerable<Subscription> Subscriptions => _subscriptions;

            IsActive => true;
            public DeletedUser Delete() => new DeletedUser(Name, DateTime.Now);
            public void AddSubscription(Subscription s) => Subscriptions.Add(subscription);

        }

        class DeletedUser : User {

            public DeletedUser(string name) : base(name) { }
            public DateTime DeletionDate {get;}
            IsActive => false;

            public DeletedUser(string name, DateTime deletionDate) : base(name) {
                this.DeletionDate = deletionDate;
            }

            public ActiveUser Reactivate() => new ActiveUser(Name);
        }

<comment><USER6> But someone else could create a subclass breaking the invariants. It's possible to avoid this by making the abstract class's constructor private and nesting the two subclasses inside of the abstract class, but this is not idiomatic. If you have to work that hard then most people won't bother, while in F# it's very natural to create such a design.

<comment><USER7> It is easy to do in C# and I do it often (seal your concrete subclasses if you are paranoid). F# does provide better syntax for it though...I wouldn't be surprised if under the covers they are using classes. C# still doesn't provide pattern matching to make it very useful...but someday I hope that happens.

<comment><USER8> Yes, it does use classes under the covers. I've never consistently used an OO language before, but I've been using C# lately, and knowing how F# can be built on top of a VM that was built for C# has definitely helped me to bring some of these concepts with me. I'm probably not writing idiomatic C#, but I think I'm okay with that.

</comment></comment></comment></comment><comment><USER9> And now you've baked your understanding of reality into your type system or your invariant contracts, you come to write some code that actually works with this API and realize you've made a terrible mistake, because when you delete a user, you need to know which subscriptions to cancel, but you've already thrown that information away as soon as you called 'Delete()'. Maybe we should restrict you from deleting a user while they have active subscriptions? Well, that's easily accomplished with a C# invariant, a little harder to bake into the F# Type union.

In general, though, it turns out you often need to be able to have objects in an 'illegal' state some of the time. "Zip code is a mandatory field" \- but that doesn't mean you can't save your order form for later if you need to go and look up the zip code. It's generally best to validate objects as being 'eligible' for a particular operation, not to prevent them from being ineligible altogether - An object with no zipcode _can_ be saved, but it _can 't_ be submitted. Structuring that sort of thing into a type system - <USER3> doable - is probably not idiomatic in either F# or C#.

<comment><USER10> If you're experiencing some sort of mismatch with your model, it means that your model is incorrect.

<comment><USER9> But if your model is churning every time your understanding of the business rules changes, then you have a different problem.

<comment><USER11> Your model will usually be incorrect because in all but the most trivial applications the model will be the result of experimentation. Even if you "accurately"[1] model the business rules, those rules themselves are subject to change as the business revives it's model of the market, or customer relationship, or regulatory environment, or whatever.

The main selling point of extreme late-binding (e.g. ad-hoc polymorphism, dependency injections, message passing, etc) is that lets you quickly revise your model.

[1] Whatever that means.

</comment></comment></comment></comment><comment><USER12> The F# code is no doubt more elegant because of discriminated unions and pattern matching, but the C# code in this comparison is a bit lazy/sloppy if you ask me.

I know it's a made up example to showcase discriminated unions, but it becomes a bit of a strawman to suggest that C# doesn't even allow representing discriminated unions. It does: through inheritance and tons of boilerplate code.

The correct demo I think would have been to make the _correct_ type (which doesn't allow invalid states to be represented) in both languages, to show how in C# it required maybe hundreds of lines, and in F# it's just a few lines.

Under the hood, almost exactly the same types are created from F#, where the F# types when seen in C# or IL of course look very much like the types you had to meticulously type in C#.

<comment><USER13> But no.

The point was to show how when you're thinking in a language that supports algebraic types and pattern-matching, _you automatically exclude states that can 't exist_.

It's not that the underlying CLR or IL is any different given the same solution -- that's just measuring a language's verbosity. It's that some language constructs automatically lead you down the path to correct code without having to boil the ocean.

Sidebar: I would have tightened the F# code up a bit. No need to have the Name string repeated in both types.

<comment><USER14> Or, you could use a class Hirarchy with a User abstract class and ActiveUser and DeletedUser subclasses and use the type system to enforce the constraints.

Using a nullable field and an enum is hardly the standard way in C#.

<comment><USER15> But unfortunately it is the one a lot of C#'ers reach for because it is the smallest amount of code in that language and often results in the least refactoring effort.

A properly designed model in C# like suggested is a large number of lines of code. And then because there is no pattern matching, you have to hand-roll your type checks/casts and make sure have that method throw an unconditional exception at the end for literally impossible states. Then if you make a change to this model, i.e. you add a new "SuspendedUser" subclass, you have to make sure you go through the codebase to update all those places you wrote a hand-rolled "pattern match" against that type. Because the compiler won't warn you about an unrepresented state on your type checks. And so then you have to make sure the whole project team is aware and you have to make sure new hires are familiar with the patterns being used. So yeah, the problems just snowball and then you wonder why you didn't just use a more appropriate language in the first place that has already taken complete care of all these trivial programming issues.

</comment></comment></comment></comment><comment><USER16> "The technique C# traditionally uses to deal with illegal states is called design by contract"

That's not really true. Code contracts are just a library , it's certainly not "traditional" in C# to use that to check for invalid state. Traditionally you just check the value before assignment. And if you do this your entire problem "goes away".

Gotta say this is one of the most contrived "F# is better than C#" example i ever saw.

<comment><USER17> > Traditionally you just check the value before assignment. And if you do this > your entire problem "goes away".

I wouldn't say spreading null checks and forgetting them all over your code makes any problems "go away".

<comment><USER16> Yes, you're right. It's better to blindly do assignments and use code contracts to check the state after. Much cleaner. </sarcasm>

<comment><USER18> Ever hear the term "false dichotomy?"

</comment></comment></comment></comment><comment><USER19> While the solution described is cool, it only applies to problems that can be solved with union types in F#.

That's cool, but things get much more complicated when trying to describe the concept of a non-empty list (still possible, but I don't believe is included in F#'s library), or near impossible when trying to describe things like a number within a certain range, or various relationships between the arguments of a function or of a type.

I mean, when you're constructing something like "Segment(x, y)" (or "Segment of double * double" in F#, not sure if I got the syntax right), how do you express that the X coordinate needs to be lower than the Y coordinate? And then the biggest modern challenge is to model state machines for asynchronous communications, which implies working in the presence of non-determinism. Good luck modeling that with a static type system.

Basically there are things that can be expressed in a statically typed way, by means of a good enough type-system, but there are always invariants that can only be checked at runtime. Hence assertions sprinkled in the code are still valuable even in a language like F#, because if you're going to fail, it's better to fail as fast as possible.

<comment><USER20> Can't comment on F#, but in Haskell you'd create a special datatype and use smart constructor which only allows to create a value which conforms the requirements:

        data Segment = Segment Double Double

        mkSegment :: Double -> Double -> Maybe Segment
        mkSegment x y
          | x < y     = Just (Segment x y)
          | otherwise = Nothing

There are things you can check at compile time, and for that F# and other strongly typed languages are great. And if that's impossible they can still _force_ you to do these checks at runtime.

And with such great support for custom types, you can rely on complex invariants in large parts of your application. In the example above, if you have a `Segment`, you _know_ that x < y, even if the compiler can't prove it.

<comment><USER19> So what stops anybody from constructing a Segment manually, bypassing mkSegment?

Assuming that you can make Segment's constructor private, that's indeed a good pattern sometimes, but leaving mkSegment as the only way to build a segment will make working with segments pretty inconvenient. Imagine that what you usually want to do with segments are intersections and unions and if the original segments already have this x < y invariant, then the algorithms, if correct, will also have it. Therefore forcing usage of mkSegment will be a pain in the ass, because then you have to deal with the Maybe monad everywhere.

As @pron is saying, this is still a runtime check. And the problem is, there is no need for it unless you receive outside input that needs to be processed. Otherwise the internal algorithms should always respect the contract anyway. Consider this ...

        intersect :: Segment -> Segment -> Maybe Segment

What would a Nothing result mean? Would it mean that the 2 segments do not intersect, or would it mean that one of the segments was invalid? Treating the error in this signature is totally unneeded and forcing usage of mkSegment would do exactly that.

In Scala I sometimes use the mkSegment pattern that you described when receiving data from the outside (like from the database), but in this particular instance I prefer doing the following, because of the above reasoning (i.e. Segments should already be valid, input should be validated elsewhere, if we've got invalid segments then we need to fail as fast as possible):

         case class Segment(x: Double, y: Double) {
           require(x <= y)
         }

And I find this to be totally fine, in addition to whatever the static type- system can pull off.

<comment><USER21>
        intersect :: Segment -> Segment -> Maybe Segment

> _What would a Nothing result mean? Would it mean that the 2 segments do not > intersect, or would it mean that one of the segments was invalid?_

The way I see it, it can only mean that they do not intersect, and _never_ that one of the segments was invalid. This is because a Segment is guaranteed to be valid by construction; after all, that's precisely the property you bought by using _mkSegment_!

<comment><USER19> Yes but by using _mkSegment_ in the implementation of _intersect_ , you have to treat its _Nothing_ result, even though it can never happen and so you either end up with this reflected in the signature of _intersect_ itself, or you cheat in the implementation of _intersect_ by assuming that _Nothing_ will never happen, which would defeat the purpose of _mkSegment_.

<comment><USER21> It's a bit cumbersome, yes, but I don't think it defeats the purpose of _mkSegment_.

Let's see: because _mkSegment_ is the only way to construct a _Segment_ , you know the arguments to _intersect_ are valid. So there cannot be any doubt about the meaning of _Maybe_ in the result; it simply cannot refer to invalid arguments. There is only one other possible meaning: that the segments don't intersect, which is the idiomatic use of _Maybe_ (another reason why I wouldn't use _Maybe_ in this case to signal an invalid argument: "which argument?").

Yes, this means that even if there is an intersection, _mkSegment_ forces you to handle the _None_ case, even though you know by construction this will never happen. It's annoying but nothing too terrible. I don't see how this is cheating; you are simply using a property that the type system is unable to catch... but this property _exists_ nonetheless.

</comment></comment></comment></comment></comment></comment><comment><USER22> It would require some type checking and casting (or runtime exceptions) but wouldn't the C# equivalent to the F# approach be abstract class User, class ActiveUser : User, and class DeletedUser : User

<comment><USER23> I believe this is what the author is referring to at the end:

>Unfortunately, the lack of discriminated unions and pattern matching makes the F#'s approach mostly unbearable to implement in C#. It's possible in some simple cases but still remains pretty tedious.

<comment><USER14> Good point. No, I don't believe that's what they mean there. The OP defines the F# version user as a union of either an activeuser or a deleteduser.

The C# idiomatic way would be to use an abstract class and implement two subclasses.

The difference is that in the C# way someone could in theory (if they're your evil wizard arch nemesis for example) create a third user subclass and harm the type soundness. In practice you can guard against that as well if you really have to guard against evil wizards.

</comment></comment></comment><comment><USER24> I don't think there's anything stopping from implementing ActiveUser and DeletedUser as separate classes in C# as well? It's much more succinct in F# but so is pretty much everything else.

</comment><comment><USER25> > _Design by contract_

Back in the day we used to call it an _assert_ , sprinkled it over code to cover the invariants and generally didn't make much fuss about it. Kids these days... "design by contract"... such words, much wow :-P

<comment><USER26> Design by Contract isn't just asserts. The only thing that contracts and asserts have in common is that they are expressed as semantic predicates.

DbC formalizes the idea of a contract (hence the name) between the caller and callee (in Eiffel parlance, the client and supplier of a service) and what each expects of the other and is part of the interface of a class.

Accordingly, there are rules for contracts (visibility of symbols used in a contract must match the visibility of the function it is attached to, how contracts are related to each other via inheritance, etc.).

It is not a terribly complicated concept, but it's also not just asserts.

<comment><USER27> > Design by Contract isn't just asserts.

That's exactly what it is, but it's a very specific style of asserts with very specific rules as to what and when to assert; it is however, still just a bunch of asserts.

<comment><USER26> Okay, then explain to me how (say) in C++ you can annotate pure virtual methods with contracts or how inheritance of contracts can be done in C++, assuming you want to implement them using asserts. For that matter, how do you implement class invariants, which need to be checked before and after each qualified call to an instance of the class, but not when the call is unqualified?

The other essential part that asserts don't really capture is that contracts (as pre- and postconditions) are part of the API, while asserts are part of the implementation.

<comment><USER27> > in C++

You can't blame me because some language you choose has limited meta abilities and doesn't allow you to place asserts anywhere. An assert is a generic concept that you can do in any language, and in languages with meta-facalities all of that is trivial to do, you're too focused on "where" the assert is in your specific language, but DBC came from Eiffel, not C++, and checking conditions or blowing up is an assert no matter where it occurs. DBC is cool, the places DBC chooses to do it's asserts are also a big part of what DBC is, but it's still all just some asserts in creative places under creative inheritance rules.

<comment><USER26> Well, if you are sufficiently fuzzy when it comes to equivalence, then every programming language is just about shuffling bits around registers and they're all one and the same thing.

But in the end, interface (contracts) and implementation (asserts) aren't actually the same thing. Having commonalities is not the same thing as being the same.

<comment><USER27> Well I'm not going to argue about it, but I agree with OP, they're just asserts used in an idiomatic way.

</comment></comment></comment></comment></comment></comment></comment><comment><USER28> Granted the F# approach is somewhat nicer, but I don't think the C# approach with contracts is too bad (no recent experience with .Net - 6yrs ago contracts were painful to use), but you also could go the immutable route and via a method call easily return a new instance of User and enforce the invariant prior to creating a new instance etc.. It's a minor issue in the end, the bigger issue is that your client/stakeholder knows what they actually want and you actually capture those in-variants exhaustively and correctly (implementation is minor, F#/ocaml/haskell can't save you here)...

<comment><USER29> AFAIK, code contracts in .NET still have all the issues they had several years ago. The absolute worst one being that you need to install something for them to actually work. This means different computers will have different code behavior.

</comment></comment><comment><USER30> In my opinion and from the comments I think that encoding one state is not a problem either in C# or F#. Now assume we have to add an additional state to a user and all proposed subclassing solutions in C# turn out to be what they are: not optimal.

My biggest problem with OO is, that it only allows us to structure code in a one dimensional way (inheritance) but in reality we will face more complex scenarios. and even this way is increasingly discouraged: composition over inheritance...

<comment><USER31> C# certainly has other options to straight inheritance like explicit interfaces and extension methods.

</comment></comment><comment><USER32> _We can depict this solution in the following way:_

      [table labeled :Users:]

In my opinion that's a better way of encoding the desired behavior than either the C# or F# code by several orders of magnitude. It can be read to find out what privileges a user state allows. It can be read to find out what user states is required to access a privilege.

The key is that tables are readable. By anyone. Even non-programmers. All the behavior is right there. The question about what's the best way to represent it in code is not F# versus C#. It's automatically versus wrong. The table should be the point of truth. [1]

[1]: The point of departure is Aaron Brooks' idea of live specification. I don't claim to accurately represent his view. Listen for yourself here: [http://blog.cognitect.com/cognicast/074](http://blog.cognitect.com/cognicast/074)

</comment><comment><USER33> Be good to also compare this to SQL databases like PostgreSQL, where you can have quite complex check constraints, non-nullable columns and unique indexes. If done properly it can make it literally impossible to insert bad data into your database.

</comment><comment><USER34> It's a contrived example. There is no need to store the "state" of a user if you can infer it from other state. Just define a "deleted" user as a user with a deletion date...

Modeling is hard, maybe it should be done more accurately...

<comment><USER12> And even if it was required (Say there were 3 states) it's an obvious smell to have a field in a type that is used only in one "state" of the object. The presence of such a field is the most obvious clue that one needs a new class for that state.

<comment><USER9> That's far from a universal truth.

Only US users have a 'social security number' field. Should US users be a different class than German users?

Only cars have a 'passenger count' field. Only electric vehicles have a 'battery capacity' field. What type system can accommodate both Teslas and Harley Davidson LiveWire bikes?

<comment><USER12> Social security, maybe a field can be of a "national identifier id" number? I have an id number but parsing and validating is different from the us version. Since it's a different format and different logic I don't see why another type wouldn't be useful.

Passenger number: "0" seems like a valid number that can make sense even for non-passenger cars.

I agree it's not black and white, though.

</comment></comment></comment></comment><comment><USER35> This is all very well for the single binary state of the example, but as the number of states increases, do you not get a combinatorial explosion in the number of types and state-transition functions?

<comment><USER36> This is my concern with F# for sure (and I like F#, though I haven't used it in anger sufficiently). When using Scala, I had to minimize the times I did this sort of thing, usually across a single axis rather than the multiple ones I'd want to do it across.

Which doesn't mean I dislike the whole concept, but it's way more limited than this article wants you to think.

</comment></comment><comment><USER37> What would be the approach if user had another state such as RestrictionLevel {admin, normal}. Would the we make a subsclass for every combination between actibe and RestrictionLevel?

</comment><comment><USER38> Isn't it related to phantom types ?</comment>


Open letter to Yahoo's Marisa Mayer - <AUTHOR> http://mrsniffen.tumblr.com/

<comment><USER2> To save others the trouble of figuring it out, it's parody.

<comment><USER3> It took me a few paragraphs to gather that, but this just means it was really well done. I appreciated the "PS" components especially. I think they made the parody aspect most clear (other than the pop culture references).

</comment></comment><comment><USER4> As a person in an office where gotomeeting is the norm, none of the executives ever come into the office and on a daily basis projects are given to programmers or graphic designers that are ill-concieved, needed immediately, without copy or specifications other than a 3-4 hour conference call on what they think they want.

In-person communication is valuable. I feel like we're missing something here. Sometimes telepresence is impersonal and disrespectful. The CIO continually butchers a few people's names. You'd think that after 3 months of talking to these people on a daily basis he'd pick up on his incorrect pronunciations.

</comment><comment><USER5> exactly the kind of guy we've been looking for! But alas, you're a dedicated Yahoo, so i hope you don't mind if we borrow this portion of your post for our Network Operations Director job description,

"From my motorized chair/exoskeleton I can maintain every server on the grid. Displays on hovering glass panels indicate data flow, cloud assets, employee location and emotional state. (Green = joy. Blue = despair.) Having tied all system function to eye movement, I can work up to fourteen days completely motionless...."</comment>