> I cannot think of a reason why the designers chose to deviate from the principle that single is bitwise and double is logical here,

That's not the principle in the first place; once you realize that, it makes more sense.

The better way to think of `&` vs `&&` is not *binary* and *Boolean*.  The better way is to think of them as *eager* and *lazy*.  The `&` operator executes the left and right side and then computes the result. The `&&` operator executes the left side, and then executes the right side only if necessary to compute the result.

When you think of it that way, it becomes clear why there is no `!!` and no `^^`.  Neither of those operators have the property that you can skip analyzing one of the operands; there is no "lazy" `not` or `xor`.

Other languages make this more clear; some languages use `and` to mean "eager and" but `and also` to mean "lazy and", for instance.  And other languages also make it more clear that `&` and `&&` are not "binary" and "Boolean"; in C# for instance, both versions can take Booleans as operands.