What "banks" did, was take a lot of "similar" mortgages (rate,maturity, etc.) and bundle them into a financial instrument. The mortgage itself is no longer something that can be negotiated, it is part of a larger financial formula and changing it requires *all* the share holders of the instrument to be informed and consent.
It's not nearly as clear-cut as you put it. The loan servicers normally have some latitude in modifying terms on loans where default is reasonably imminent, as a form of loss mitigation. Skim this link for a brief explanation of this toward the beginning.
In any case, even if you assume a modification that the servicer isn't ordinarily allowed to do, it doesn't follow that all shareholders must consent to that modification. It really depends on how the instrument is structured and managed. A really simple example: if the investment is structured as a holding corporation for the assets, approval for modifications would be subject to the bylaws of the corporation. Modifications could be at the discretion of the management of the corporation; they could require approval from the board; or they could require shareholder vote. There's no general answer.
Zero. The bane of all. It was the gateway math to all modern problems. It would be so much simpler with just countables. Surely the current crisis, measured in trillions would look so much better without all those zeros.
Yeah, I know this is a joke, but I've still got to point out the following: a positional numbering system doesn't actually need a zero digit. Throw out zero, and use instead a digit 'X', whose value is ten. Then you get:
My problem is that null references are typically used to signal the ends of lists or the place where the tree ends. I could see using a variant type for this. Instead of pointing to null, the next to the last list element would point to a value that had the type 'last list element' and no pointer inside it.
I think one thing that's confusing people in this argument is the failure to distinguish between logical aspect of data and the physical representation thereof.
Variant types, as implemented by a language like Haskell, are primarily a logical construct. A variant type is a type whose members are the union of tagged values of other specified types. This kind of definition says nothing about pointers or null references; it's all about which values are members of each type.
Singly linked lists are a variant type, whose members are (a) the empty list, (b) pairs that contain a list element and the rest of the list. This type can be physically represented in many ways, some of which will use nulls to represent the empty list, some of which will use a different primitive sigil value, and some of which will use a pointer to another memory object that signifies the end of the list. These are all equivalent from the logical perspective; the choice between them comes from implementation details, or application requirements that restrict the physical representation (which is why C is good for low-level programming and Haskell is not, since C gives you more and easier control over how your data is physically laid out).
And there would be four varieties of tree node, leaf, left filled, right filled and both filled.
This is probably the wrong kind of definition at the logical level, because it has more subcases than it needs. In pseudo-Haskell, here's one that would be simpler:
data BTree a = Empty | Node (BTree a) a (BTree a)
In English, a BTree of element type a is either the Empty tree, or a Node that has three fields: a left BTree of a, an a, and a right BTree of a. (This definition treats a "leaf" as a node where both branches are the empty tree.)
Not necessarily. You could mandate default constructors that would be invoked every time that an unreferenced object occurred, so Strings unless explicitly initialised would refer to "", user types to whatever the default constructor produced, and so on.
But that would be very limiting indeed. Basically, in that situation, you just make it a lot harder to encode "out of band" information like the absence of a value; if you encode something like "no input was provided" as the empty string, then your program cannot easily distinguish "no input was provided" from "the empty string was provided as input." You'd need to carry around some other piece of information, for example a boolean value, to distinguish between these two situations. If you did this a lot, you might find yourself putting the boolean value and the string together in a struct. But what you're doing then is basically your own ad-hoc implementation of an algebraic data type.
Is it not a tad arrogant to claim that he single-handedly is responsible for a billion dollars in mistakes?
Frankly, just on its own, without more context, it's not possible to tell. It all comes down to whether he's saying it to boast of how important he is, or whether he is simply admitting a mistake that was widely copied by others.
Null checks are cheap and the idea of a compiler removing mine scares me.
Null checks are cheap indeed, but there are still bound to be places where removing them can be a useful optimization. I've thought harder about it, and the one sort of case where I think it might be valuable is when inlining code into inner loops.
I don't think you should be any more scared of the compiler removing such checks than you are of compiler optimizations in general. In theory, the compiler can remove checks or alter the way they are done if it can prove the program won't be affected. In practice, actual compilers certainly do have optimization bugs (check out this bug in Java). My point? You should be as scared of of your compiler removing null checks about the same amount as you are scared of compiler bugs already. (And IIRC, Java already does null-check elimination.)
You still have to check at runtime - you can still get null references where none should exist
Yes, you have to check at runtime, but the places where you do have to check are restricted: only places where you convert from nullable to non-nullable. This means that null pointer exceptions are thrown closer to where the nulls originate, instead of having the current situation, where a null erroneously generated in one place in the code can propagate through thousands of lines all over the place before it lands somewhere where a null is really not tolerated.
Consider the situation of apples. If you have an apple, then something is in your possession. If you don't have an apple, what do you have? Do you have some sort of object that depicts your lack of an apple? Obviously not. Yet in the world of computers, we have this special piece of data that shows our lack of data. It's a bit like getting a certificate that you have no apples. The certificate accomplishes nothing except to fill a space that does not need to be filled.
By thinking about this in terms of "having objects," you're distorting the whole issue.
Think about it instead in terms of encoding facts about the world. If we want to record the fact that you have an apple, and that I do not, there are several ways we could choose to encode this. Some of them would require you to explicitly have an informational token for each fact, so that you needed one piece of data to encode "Joe has an apple," and another one to encode "Mary doesn't have an apple." Another scheme might have you just encode who has an apple, and specify that if it is not explicitly recorded whether some specific individual has an apple, you should infer that they do not.
One kind of representation is appropriate for some applications, and one for others. Vague generalities about apples and "having" do absolutely nothing to guide how one should encode information in a computer.
No, Java chooses a faster, implicit, option type - it's the same thing, just not explicitly stated. The only difference here is that the language doesn't make you check for null.
Um, there is zero reason why implicit option types would be any faster than the equivalent base types. Option types can be trivially implemented as compilation time type checking, with implicit nullity checks when you cast an option type to its base type. The physical representation of the data and the generated object code could be exactly the same; the only difference is that when you use the base types, the compiler proved at compilation time that certain expressions never evaluate to null.
Hell, I wouldn't be surprised in fact if there were optimizations that are made impossible by having every type implicitly be an option type. Basically, it makes you unable to optimize away situations where the existing runtime system needs to check whether a reference is null. (It's a cheap check, yes, so it might not make a difference in practice, but as a general rule, stronger type system = more optimizations available.)
From the perspective of comp-sci, is that a correct solution? The answer is "no". An absence of data should simply be an absence of data, not a piece of data that represents the absence of data.
How is that "the perspective of comp-sci"? And more importantly: what the hell is that supposed to mean in the first place? What is "absence of data," and how do we distinguish it from "a piece of data"? Isn't it all just coded information and rules for interpreting it, in which case, the "absence of data" and the "presence of data" are just a distinction over coded states?
Your "solution," BTW, is pretty much equivalent to using boolean false as the linked list terminator. Yes, I know it's not exactly the same, but basically, it relies on the negation of end.next evaluating to true. That's not meaningfully different from returning null for a failed lookup; you're basically changing (a) the choice of sigil (return something other than null whenfoo.next is a failed lookup), (b) the semantics of negation (so that the sigil counts as false for boolean negation).
No, "absence of data" in the Date of Death column simply means that we don't have it, whatever the reason may be - it simply doesn't matter as far as the database is concerned.
No, it matters enormously as far as the database is concerned. The meaning of data is part of the general data management problem that databases are supposed to address. If somebody somewhere concludes that a dead person is alive when they should have concluded that they are dead, but their death date is unknown, the database has probably failed, in one way or another.
In this case, the problem can be either data that's not normalized properly, or abuse of NULL to mean different things in different contexts. With the first kind of solution, you might record deaths and their dates as a separate base relation. With the second type, you introduce a finer distinction than just value-vs.-NULL; you'd have to distinguish "value doesn't exist" from "value exists, but is not known."
I really think that database systems ought to have union data types, like ML and Haskell do. Then you wouldn't have to overload NULL; you'd just use your own enumerated alternatives.
Yes, it's a neat technique. It's also very old and obvious. Google's implementation is also good, but this stuff is just not rocket surgery. It's just a simple pattern of how to massively parallelize some types of computational tasks.
But somehow, just because some dudes at Google wrote a paper about it, it's become the second coming of Alan Turing or something among some silly folks. Hell, a couple of weeks ago somebody was saying on the comments here that MapReduce was a good alternative to relational databases. Now that is silly.
See my post right above yours. Basically, one way of "abolishing null" is to replace it with more general variant type features that allow you to guarantee that nulls can only occur where your program declares they may. In that case, the answer to your question is simple: if your hash table's if of type Map, then the get operation's signature is something like this:
nullable V get(K key)
The idea behind this sort of solution is that the nulls problem isn't the existence of nulls, but rather, the fact that the language type system forces every type in your program to admit null in its domain. The solution is to distinguish between the type of a Foo and the type of "Foo or nothing."
Variant types (or, put more generally, algebraic data types) are indeed a general solution for this problem, that can be reused for countless others.
The simplest example here is the way you define linked list types in a functional language like Haskell. In pseudo-code (yes, I know this might not be valid Haskell code):
data List a = EmptyList | Node a (List a)
This is a data type declaration that says that the type "List of a" is either the singleton EmptyList value, or a 'Node a' value, which contains (as struct fields, basically) an element of type a and a List of a. (In case it isn't clear, 'a' is a type parameter here; so a list of strings would be 'List String', a list of integers would be 'List Integer', and so on.)
This works just as well to allow you to define generic nullable type constructors (which the standard Haskell library provides):
data Maybe a = Nothing | Just a
The type 'Maybe String' represents a value that might be either 'Nothing', or 'Just x' for some x of type String.
No, it isn't false. SQL is based on a three-valued logic, not on boolean logic, and comparisons involving NULL evaluate to the third truth value, commonly notated as unk (for "unknown"). This is treated equivalently to false in most contexts, but is treated the same way as true in check constraints. Read up.
The other alternative to forced nullable types in your language is to have labeled union types, à la ML/Haskell. This feature's scope takes care of the cases where you genuinely want null, and of enumeration types in general, too.
The Haskell type system allows you to define types that are an "or" of several named subcases. Each subcase can have values of other types as contents, or nothing. So, for example, in Haskell you can define the following type, called Maybe (I hope I get the syntax right!):
data Maybe a = Nothing | Just a
This is a parametric type, parametrized over a type variable, 'a'; thus you can use the Maybe type constructor to construct types like Maybe String, Maybe Integer, Maybe Tree, etc. A variable of type Maybe String can take two kinds of value:
var1:: Maybe String var1 = Just "this is a string"
var2:: Maybe String var2 = Nothing
What this implements is the idea that a variable whose value is always an object of type t has a different type than a variable whose value is either an object of type t, or some designated, extra value that means "nothing." Then you code can be written so that contexts where it doesn't make sense to have nulls make use of the plain types, contexts that really require nullable types use those, and that to go from a nullable context to a non-nullable one you need to perform some sort of type cast that checks and handles the null case.
This falls out for free from labeled union types, but it would be very easy to get a limited version of this in a language without labeled unions, by nullability as a sort of type annotation, and defaulting all type declarations to not nullable. In this model, a variable cannot be null unless you've declared it to be nullable, and whenever you need to pass a value held in a nullable variable to a function whose arguments aren't nullable, you'd need to convert the variable's value to a non-nullable type, which would perform a null check. You'd have a compilation-time guarantee that the only places in your program where nulls can occur is those places where you've declared they can.
Yeah, but wouldn't the first thing you'd do in the system API design of any non-null language be, the creation of a singleton object instance of the superclass of all objects, named 'null' ?
If nulls truly are valuable in some cases, then the correct thing to do is to give the language optional nullable types. A variable of type 'Foo' is guaranteed to refer to some Foo, while a variable of type 'nullable Foo' might have null as its value. The compiler would then reject programs that tried to use variables or expressions of type nullable Foo in contexts that expected a Foo, which would force the programmer to write code to handle the null case in order to convert nullable Foo to Foo.
The best examples we have of languages with no nulls is the ML/Haskell family, and they get away without having nulls by having labeled union types, which is a more general version of this idea. For every type t, in Haskell there is a type Maybe t, whose values are either something of type t, or a sentinel that stands in for "nothing."
Also, apart from 'null' there are loads of parameters than can have illegal ranges and must be checked to be proper.
And typeful programming can help you guarantee that your program is free from such errors, in many cases. Basically, construct a restricted type that encapsulates another, more primitive one, and have the constructors for the restricted type do the range checking. Then you have a compilation-time guarantee that all objects of the restricted type fall within the range you want.
He wants insurance products or services that protect you against the risk that you may need expensive care over the long term. His problem is that by allowing people who believe they won't end up in this category to opt out of paying for that, it becomes impossible to insure against that risk.
The insurance plan gives you positively perverse financial incentives. Preventative health care is relatively cheap, but still a significant expense. Catastrophic health care is obscenely expensive, and you don't have to pay for most of it. This gives you a financial incentive to skimp on preventative health care and no financial incentive to avoid the need for six-figure medical bills.
And to make it worse, by focusing on the risk of a one-time six-figure medical bill, you end up ignoring the very real risk that you may end up with recurring four- to five-figure medical bills for a span of 30-40 years. That's the big problem with all of these proposals for offering only catastrophic coverage: the proposed schemes cannot possibly protect them against the very real risk of long-term health problems, because allowing people who enjoy long-term health to minimize their insurance costs creates adverse selection that makes it impossible to cover the claims of those who suffer long-term illness.
If individuals could get the same rates as big insurance companies, then I'd definitely prefer to have a cheap insurance plan for only big emergencies, and keep the difference in an HSA.
I mean, seriously, how would that plan you propose actually work? If the healthy people are paying very little for insurance, where is the money going to come from to pay for the health care costs of the ones that get sick? (And when I say, "get sick," think of something along the lines of discovering at around age 30 that they have a congenital problem that requires periodic, costly attention for the rest of their lives.)
Basically, the choice you're expressing here is a form of adverse selection, where all the "healthy" people try to keep their health insurance costs to a bare minimum. This is a recipe for health "insurance" that doesn't actually cover you when you get sick. If the only people who opted for comprehensive coverage are the people who need it, then there won't be money to insure against risks that require you to get need comprehensive coverage, period.
Make sure to remember this: you shouldn't be trying to insure yourself only against "big emergencies," as you put it: one-time events that require a relatively brief period of very expensive coverage, but which you recover from thereafter. You also need to insure yourself against the risk that you may end up needing moderately expensive care for a chronic condition over 30-40 years. This is the reason why the cheap insurance you would like to have is broken, because it cannot protect you from many very significant health risks that you face.
It should be different to keep you alive? What's so special about you that I should have to pay for that?
Other people have provided better responses, but I'll try to give one that's based on nothing but self interest: you could unexpectedly find yourself in that situation instead of him, in which case, it would very much be in your interest that he should have to pay to keep you alive.
I think the whole problem there stems from how health insurance morphed to health care. If you want to go see a doctor every year, pay for it. If you get run over by a truck, that's what insurance is for. Insurance is for the unforseable, not the routine. The problem is the line that has to be drawn, and it becomes a pretty grey area, so it's ended up that the insurance company is expected to pay for everything, which of course drives up the cost.
The problem with what you're saying is that the sort of routine care you say insurance shouldn't cover actually doesn't cost much to provide. Health care expenditures are really one of those 80/20 phenomena: the vast majority of the cost is spent on the health care of a small number of people.
By making people pay for it out of pocket, all you do is disincentivize routine care (which is cheap to provide). You don't put a dent on the major sources of health costs, and what's worse, you prevent people from getting treated early on, while it's still relatively cheap to do so.
The whole point of the article is that the iPhone is doing fairly well and people like it a lot over there -- the main thing holding it back is its carrier, which is sort of an underdog.
I didn't quite read it like that. Yes, I did get the impression that the carrier is holding it back, but also that the feature set isn't really tailored toward the Japanese market.
And it turns out the iPhone is primarily responsible for major growth in that carrier anyway.
Yup. My impression was that the iPhone is facing some significant obstacles over there, but doing reasonably well regardless. It sure sounds like Apple could improve its sales over there if it thought more carefully about the feature set and the carrier deals.
The "kick me" sign is a flawed analogy. The guy walking with a "kick me" sign was the victim of somebody else who went to a non-trivial effort to ridicule him. When you remove the sign, you make it known to him that somebody was perpetrating a continued attack on him, and you make the attack stop.
When you call the guy who makes the common orthographical error a "fucking idiot," on the other hand, you're the one who attacks and ridicules him. It makes no difference whether you call him a fucking idiot directly, or whether you leave a silly out by "only" saying that he "sounds" like a fucking idiot. In either case, you're the one who escalates the situation by taking a perfectly good ongoing conversation about something that the participants care about, and changing the topic to the question of whether the guy is a fucking idiot or just sounds like one.
Yeah, you're a fucking hero for saving him from his orthographical errors, aren't you?
Not pointing it out and letting them go through life with the misguided impression that nobody cares that they sound like a fucking idiot is even worse.
It is only fucking idiots who believe that people who mix up "losing" with "loosing" sound like fucking idiots.
Yes, some people aren't very good at orthography. So what? What chain of reasoning could possibly lead to "they're fucking idiots," without invoking something along the way like an insistence that everybody cater to your petty pet peeves?
It's not nearly as clear-cut as you put it. The loan servicers normally have some latitude in modifying terms on loans where default is reasonably imminent, as a form of loss mitigation. Skim this link for a brief explanation of this toward the beginning.
In any case, even if you assume a modification that the servicer isn't ordinarily allowed to do, it doesn't follow that all shareholders must consent to that modification. It really depends on how the instrument is structured and managed. A really simple example: if the investment is structured as a holding corporation for the assets, approval for modifications would be subject to the bylaws of the corporation. Modifications could be at the discretion of the management of the corporation; they could require approval from the board; or they could require shareholder vote. There's no general answer.
Yeah, I know this is a joke, but I've still got to point out the following: a positional numbering system doesn't actually need a zero digit. Throw out zero, and use instead a digit 'X', whose value is ten. Then you get:
1, 2, ..., 9, X, 11, 12, ..., 19, 1X, 21, ..., 98, 99, 9X, X1, X2, ..., X9, XX, 111, ...
8X = 8 * X + X (ninety)
X2 = X * X + 2 (one hundred two)
I think one thing that's confusing people in this argument is the failure to distinguish between logical aspect of data and the physical representation thereof.
Variant types, as implemented by a language like Haskell, are primarily a logical construct. A variant type is a type whose members are the union of tagged values of other specified types. This kind of definition says nothing about pointers or null references; it's all about which values are members of each type.
Singly linked lists are a variant type, whose members are (a) the empty list, (b) pairs that contain a list element and the rest of the list. This type can be physically represented in many ways, some of which will use nulls to represent the empty list, some of which will use a different primitive sigil value, and some of which will use a pointer to another memory object that signifies the end of the list. These are all equivalent from the logical perspective; the choice between them comes from implementation details, or application requirements that restrict the physical representation (which is why C is good for low-level programming and Haskell is not, since C gives you more and easier control over how your data is physically laid out).
This is probably the wrong kind of definition at the logical level, because it has more subcases than it needs. In pseudo-Haskell, here's one that would be simpler:
In English, a BTree of element type a is either the Empty tree, or a Node that has three fields: a left BTree of a, an a, and a right BTree of a. (This definition treats a "leaf" as a node where both branches are the empty tree.)
But that would be very limiting indeed. Basically, in that situation, you just make it a lot harder to encode "out of band" information like the absence of a value; if you encode something like "no input was provided" as the empty string, then your program cannot easily distinguish "no input was provided" from "the empty string was provided as input." You'd need to carry around some other piece of information, for example a boolean value, to distinguish between these two situations. If you did this a lot, you might find yourself putting the boolean value and the string together in a struct. But what you're doing then is basically your own ad-hoc implementation of an algebraic data type.
Frankly, just on its own, without more context, it's not possible to tell. It all comes down to whether he's saying it to boast of how important he is, or whether he is simply admitting a mistake that was widely copied by others.
Null checks are cheap indeed, but there are still bound to be places where removing them can be a useful optimization. I've thought harder about it, and the one sort of case where I think it might be valuable is when inlining code into inner loops.
I don't think you should be any more scared of the compiler removing such checks than you are of compiler optimizations in general. In theory, the compiler can remove checks or alter the way they are done if it can prove the program won't be affected. In practice, actual compilers certainly do have optimization bugs (check out this bug in Java). My point? You should be as scared of of your compiler removing null checks about the same amount as you are scared of compiler bugs already. (And IIRC, Java already does null-check elimination.)
Yes, you have to check at runtime, but the places where you do have to check are restricted: only places where you convert from nullable to non-nullable. This means that null pointer exceptions are thrown closer to where the nulls originate, instead of having the current situation, where a null erroneously generated in one place in the code can propagate through thousands of lines all over the place before it lands somewhere where a null is really not tolerated.
By thinking about this in terms of "having objects," you're distorting the whole issue.
Think about it instead in terms of encoding facts about the world. If we want to record the fact that you have an apple, and that I do not, there are several ways we could choose to encode this. Some of them would require you to explicitly have an informational token for each fact, so that you needed one piece of data to encode "Joe has an apple," and another one to encode "Mary doesn't have an apple." Another scheme might have you just encode who has an apple, and specify that if it is not explicitly recorded whether some specific individual has an apple, you should infer that they do not.
One kind of representation is appropriate for some applications, and one for others. Vague generalities about apples and "having" do absolutely nothing to guide how one should encode information in a computer.
Um, there is zero reason why implicit option types would be any faster than the equivalent base types. Option types can be trivially implemented as compilation time type checking, with implicit nullity checks when you cast an option type to its base type. The physical representation of the data and the generated object code could be exactly the same; the only difference is that when you use the base types, the compiler proved at compilation time that certain expressions never evaluate to null.
Hell, I wouldn't be surprised in fact if there were optimizations that are made impossible by having every type implicitly be an option type. Basically, it makes you unable to optimize away situations where the existing runtime system needs to check whether a reference is null. (It's a cheap check, yes, so it might not make a difference in practice, but as a general rule, stronger type system = more optimizations available.)
How is that "the perspective of comp-sci"? And more importantly: what the hell is that supposed to mean in the first place? What is "absence of data," and how do we distinguish it from "a piece of data"? Isn't it all just coded information and rules for interpreting it, in which case, the "absence of data" and the "presence of data" are just a distinction over coded states?
Your "solution," BTW, is pretty much equivalent to using boolean false as the linked list terminator. Yes, I know it's not exactly the same, but basically, it relies on the negation of end.next evaluating to true. That's not meaningfully different from returning null for a failed lookup; you're basically changing (a) the choice of sigil (return something other than null whenfoo.next is a failed lookup), (b) the semantics of negation (so that the sigil counts as false for boolean negation).
No, it matters enormously as far as the database is concerned. The meaning of data is part of the general data management problem that databases are supposed to address. If somebody somewhere concludes that a dead person is alive when they should have concluded that they are dead, but their death date is unknown, the database has probably failed, in one way or another.
In this case, the problem can be either data that's not normalized properly, or abuse of NULL to mean different things in different contexts. With the first kind of solution, you might record deaths and their dates as a separate base relation. With the second type, you introduce a finer distinction than just value-vs.-NULL; you'd have to distinguish "value doesn't exist" from "value exists, but is not known."
I really think that database systems ought to have union data types, like ML and Haskell do. Then you wouldn't have to overload NULL; you'd just use your own enumerated alternatives.
Oh, please, make the MapReduce fanboyism stop.
Yes, it's a neat technique. It's also very old and obvious. Google's implementation is also good, but this stuff is just not rocket surgery. It's just a simple pattern of how to massively parallelize some types of computational tasks.
But somehow, just because some dudes at Google wrote a paper about it, it's become the second coming of Alan Turing or something among some silly folks. Hell, a couple of weeks ago somebody was saying on the comments here that MapReduce was a good alternative to relational databases. Now that is silly.
See my post right above yours. Basically, one way of "abolishing null" is to replace it with more general variant type features that allow you to guarantee that nulls can only occur where your program declares they may. In that case, the answer to your question is simple: if your hash table's if of type Map, then the get operation's signature is something like this:
The idea behind this sort of solution is that the nulls problem isn't the existence of nulls, but rather, the fact that the language type system forces every type in your program to admit null in its domain. The solution is to distinguish between the type of a Foo and the type of "Foo or nothing."
Variant types (or, put more generally, algebraic data types) are indeed a general solution for this problem, that can be reused for countless others.
The simplest example here is the way you define linked list types in a functional language like Haskell. In pseudo-code (yes, I know this might not be valid Haskell code):
This is a data type declaration that says that the type "List of a" is either the singleton EmptyList value, or a 'Node a' value, which contains (as struct fields, basically) an element of type a and a List of a. (In case it isn't clear, 'a' is a type parameter here; so a list of strings would be 'List String', a list of integers would be 'List Integer', and so on.)
This works just as well to allow you to define generic nullable type constructors (which the standard Haskell library provides):
The type 'Maybe String' represents a value that might be either 'Nothing', or 'Just x' for some x of type String.
The other alternative to forced nullable types in your language is to have labeled union types, à la ML/Haskell. This feature's scope takes care of the cases where you genuinely want null, and of enumeration types in general, too.
The Haskell type system allows you to define types that are an "or" of several named subcases. Each subcase can have values of other types as contents, or nothing. So, for example, in Haskell you can define the following type, called Maybe (I hope I get the syntax right!):
This is a parametric type, parametrized over a type variable, 'a'; thus you can use the Maybe type constructor to construct types like Maybe String, Maybe Integer, Maybe Tree, etc. A variable of type Maybe String can take two kinds of value:
What this implements is the idea that a variable whose value is always an object of type t has a different type than a variable whose value is either an object of type t, or some designated, extra value that means "nothing." Then you code can be written so that contexts where it doesn't make sense to have nulls make use of the plain types, contexts that really require nullable types use those, and that to go from a nullable context to a non-nullable one you need to perform some sort of type cast that checks and handles the null case.
This falls out for free from labeled union types, but it would be very easy to get a limited version of this in a language without labeled unions, by nullability as a sort of type annotation, and defaulting all type declarations to not nullable. In this model, a variable cannot be null unless you've declared it to be nullable, and whenever you need to pass a value held in a nullable variable to a function whose arguments aren't nullable, you'd need to convert the variable's value to a non-nullable type, which would perform a null check. You'd have a compilation-time guarantee that the only places in your program where nulls can occur is those places where you've declared they can.
If nulls truly are valuable in some cases, then the correct thing to do is to give the language optional nullable types. A variable of type 'Foo' is guaranteed to refer to some Foo, while a variable of type 'nullable Foo' might have null as its value. The compiler would then reject programs that tried to use variables or expressions of type nullable Foo in contexts that expected a Foo, which would force the programmer to write code to handle the null case in order to convert nullable Foo to Foo.
The best examples we have of languages with no nulls is the ML/Haskell family, and they get away without having nulls by having labeled union types, which is a more general version of this idea. For every type t, in Haskell there is a type Maybe t, whose values are either something of type t, or a sentinel that stands in for "nothing."
And typeful programming can help you guarantee that your program is free from such errors, in many cases. Basically, construct a restricted type that encapsulates another, more primitive one, and have the constructors for the restricted type do the range checking. Then you have a compilation-time guarantee that all objects of the restricted type fall within the range you want.
He wants insurance products or services that protect you against the risk that you may need expensive care over the long term. His problem is that by allowing people who believe they won't end up in this category to opt out of paying for that, it becomes impossible to insure against that risk.
And to make it worse, by focusing on the risk of a one-time six-figure medical bill, you end up ignoring the very real risk that you may end up with recurring four- to five-figure medical bills for a span of 30-40 years. That's the big problem with all of these proposals for offering only catastrophic coverage: the proposed schemes cannot possibly protect them against the very real risk of long-term health problems, because allowing people who enjoy long-term health to minimize their insurance costs creates adverse selection that makes it impossible to cover the claims of those who suffer long-term illness.
I mean, seriously, how would that plan you propose actually work? If the healthy people are paying very little for insurance, where is the money going to come from to pay for the health care costs of the ones that get sick? (And when I say, "get sick," think of something along the lines of discovering at around age 30 that they have a congenital problem that requires periodic, costly attention for the rest of their lives.)
Basically, the choice you're expressing here is a form of adverse selection, where all the "healthy" people try to keep their health insurance costs to a bare minimum. This is a recipe for health "insurance" that doesn't actually cover you when you get sick. If the only people who opted for comprehensive coverage are the people who need it, then there won't be money to insure against risks that require you to get need comprehensive coverage, period.
Make sure to remember this: you shouldn't be trying to insure yourself only against "big emergencies," as you put it: one-time events that require a relatively brief period of very expensive coverage, but which you recover from thereafter. You also need to insure yourself against the risk that you may end up needing moderately expensive care for a chronic condition over 30-40 years. This is the reason why the cheap insurance you would like to have is broken, because it cannot protect you from many very significant health risks that you face.
Other people have provided better responses, but I'll try to give one that's based on nothing but self interest: you could unexpectedly find yourself in that situation instead of him, in which case, it would very much be in your interest that he should have to pay to keep you alive.
The problem with what you're saying is that the sort of routine care you say insurance shouldn't cover actually doesn't cost much to provide. Health care expenditures are really one of those 80/20 phenomena: the vast majority of the cost is spent on the health care of a small number of people.
By making people pay for it out of pocket, all you do is disincentivize routine care (which is cheap to provide). You don't put a dent on the major sources of health costs, and what's worse, you prevent people from getting treated early on, while it's still relatively cheap to do so.
I didn't quite read it like that. Yes, I did get the impression that the carrier is holding it back, but also that the feature set isn't really tailored toward the Japanese market.
Yup. My impression was that the iPhone is facing some significant obstacles over there, but doing reasonably well regardless. It sure sounds like Apple could improve its sales over there if it thought more carefully about the feature set and the carrier deals.
The "kick me" sign is a flawed analogy. The guy walking with a "kick me" sign was the victim of somebody else who went to a non-trivial effort to ridicule him. When you remove the sign, you make it known to him that somebody was perpetrating a continued attack on him, and you make the attack stop.
When you call the guy who makes the common orthographical error a "fucking idiot," on the other hand, you're the one who attacks and ridicules him. It makes no difference whether you call him a fucking idiot directly, or whether you leave a silly out by "only" saying that he "sounds" like a fucking idiot. In either case, you're the one who escalates the situation by taking a perfectly good ongoing conversation about something that the participants care about, and changing the topic to the question of whether the guy is a fucking idiot or just sounds like one.
Yeah, you're a fucking hero for saving him from his orthographical errors, aren't you?
It is only fucking idiots who believe that people who mix up "losing" with "loosing" sound like fucking idiots.
Yes, some people aren't very good at orthography. So what? What chain of reasoning could possibly lead to "they're fucking idiots," without invoking something along the way like an insistence that everybody cater to your petty pet peeves?