Yes, I wish things where simpler too, and I think they can/will become simpler eventually, as the current inconsistencies are probably bugs/transitional issues, rather than a final design. There are other strange manifistations of these inconsistencies that lead me to beleive this.
Also, I don't think you are right when you say that one-element tuples don't exist. Here's what the Swift iBook (latest prerelease) has to say about this (section about Types, subsection Tuple Types):
Void is a typealias for the empty tuple type, (). If there is only one element inside the parenthesis, the type is simply the type of that element. For example, the type of (Int) is Int, not (Int). As a result, you can name a tuple element only when the tuple has two or more elements.
The book also says the following about types (in general):
In Swift, there are two kinds of types: named types and compound types. / ... / There are two compound types: function types and tuple types.
So, reading that, it's clear that indeed there are one-element tuples (eg 1 or "abc"), and zero-element tuples (Void, ()), and two element tuples, etc.
Nowhere can I see anything about there being no one element tuples.
That you can not use names and index numbers (x.0, x.1, x.2, ...) on zero and one element tuples is something completely different.
I see no reason in the documentation why parameter and argument lists cannot or should not be seen as and follow the rules for tuple types, tuples, tuple patterns. This would of course mean that eg Int, and String can also to be considered as following the tuple rules (being a one-element tuple type, but that one-element tuple type happens to be the specific named type, according to the rules of Tuple types above).
Regarding your example of f(1) becoming f 1:
f(1) and f 1 simply means the same thing, it is the function f called with the argument 1 (since (1) is the same as 1, according to the rule also stated in the Swift iBook: "The parentheses around a tuple pattern that contains a single element have no effect").
That you cannot write f 1 in code is again a different thing, it's just because parentheses happens to be used in the syntax for function calls in Swift. Also calling a function doesn't have to look only like f(1) in Swift, it can also look like eg this:
func f(a: Int) { print(a) }
func callFunction<A, R>(fn: A -> R, withArguments args: A) -> R { return fn(args) }
infix operator ∘⨍ {}
func ∘⨍<A, R>(lhs: A -> R, rhs: A) -> R { return lhs(rhs) }
// Different ways of calling f with the argument list 1 (which is the same as (1), which is the same as ((1)) ...):
f(1)
callFunction(f, withArguments: 1)
callFunction(f, withArguments: (1))
callFunction(f, withArguments: ((1)))
// ...
f ∘⨍ 1
f ∘⨍ (1)
f ∘⨍ ((1))
// ...
EDIT:
I now realize that if parameter lists are to be considered tuple types / patterns, then by the quoted rule above, we shouldn't be able to name the parameter of a single parameter function ...
But at the same time, the grammar section of the Swift book again convinces me that parameter (list) types follow the rules of tuple types/patterns. Look at the grammar for function-types, the grammar for types and the grammar for tuple-types.
The grammar for tuple-types include inout for example.
The book also says the following in the sections about Function types and Parenthesized expressions:
Function Type
A function-type represents the type of a function, method or closure and consists of a parameter- and a return-type separated by an arrow (->):
parameter-type -> return-type
Because the parameter-type and the return-type can be a tuple type, function types support functions and methods that take multiple parameters and return multiple values.
/.../
Parenthesized Expression
/.../ Use parenthesized expressions to create tuples and to pass arguments to a function call. If there is only one value inside the parenthesized expression, the type of the parenthesized expression is the type of that value. For example, the type of the parentesized expression (1) is Int, not (Int).
/.../
So I think what the book says is pretty clear (and that implies that both A and B should compile), but the current behaviour/implementation is a mess.