+, accepting any number ≥ 2 of numbers and returning a number of the same type.
I’d argue that + should accept any number ≥ 0 of arguments. (With zero arguments returning the additive identity for the type[1], and one argument returning the value itself.)
(And analogously for multiplication / exponentiation / etc.)
Otherwise you end up having to special-case a bunch of things.
As an example, the ‘obvious’ identity +(*first_part, *second_part) = +(+(*first_part), +(*second_part))[2] needs exemptions for if either side has 0 or 1 element, otherwise.
(Then again, I’m of the view that from a purity standpoint you shouldn’t have non-associative functions where the inverse single-argument function is available. So e.g. don’t have subtraction. Have negation and summation.+(a, -b, -c) is unambiguous in a way that -(a, b, c) isn’t.)
then I could get behind it. My worry is that it would too often accept inputs that the user didn’t intend. Like, “this is meant to be a function, but there’s a typo twenty lines down that mean it’s being taken as a number instead”. (I have this same worry with variadic functions in general, to be clear, as well as other helpful type system features.)
So e.g. don’t have subtraction. Have negation and summation.+(a, -b, -c) is unambiguous in a way that -(a, b, c) isn’t.
I kinda hate this suggestion but somewhat share the purity instincts that generated it :p
To (ab)use Python list unpacking syntax. I would be interested in knowing the proper syntax for this identity in Haskenthetical.
I think Haskell doesn’t really have anything analagous here. With typed lists and no variadic functions, there’s not much need for it. And I think all the approaches to variadic functions I looked at here, still need the number of arguments to be known at compile time.
I’d just write it informally, as something like ”(+ a_1 ... a_n b_1 ... b_m) == (+ (+ a_1 ... a_n) (+ b_1 ... b_m)) for n, m >= 0”
or whatever ‘a function call with zero arguments’ is in this language.
Well, in standard Hindley-Milner, there’s no such thing. Every function takes one argument and returns a value, which might itself be a function.
It’s conceivable that some extension could change that, and yeah, syntactically distinguish between + the variadic function, and (+) the result of passing no arguments to +. I don’t think any of the schemes listed in this post would make that distinction though. The Zip Calculus’ version of “passing no arguments” would be “passing an empty tuple”. The typeclass approach would distinguish them by typechecking, and I think Infinitary Tuples would too.
I’d argue that + should accept any number ≥ 0 of arguments. (With zero arguments returning the additive identity for the type[1], and one argument returning the value itself.)
(And analogously for multiplication / exponentiation / etc.)
Otherwise you end up having to special-case a bunch of things.
As an example, the ‘obvious’ identity
+(*first_part, *second_part) = +(+(*first_part), +(*second_part))
[2] needs exemptions for if either side has 0 or 1 element, otherwise.(Then again, I’m of the view that from a purity standpoint you shouldn’t have non-associative functions where the inverse single-argument function is available. So e.g. don’t have subtraction. Have negation and summation.
+(a, -b, -c)
is unambiguous in a way that-(a, b, c)
isn’t.)Or maybe allow zero arguments only if said type has an additive identity.
To (ab)use Python list unpacking syntax. I would be interested in knowing the proper syntax for this identity in Haskenthetical.
Maybe! I’d want to still be able to write
(+ 1)
instead of(λ n (+ 1 n))
. But if type checking accepts all ofthen I could get behind it. My worry is that it would too often accept inputs that the user didn’t intend. Like, “this is meant to be a function, but there’s a typo twenty lines down that mean it’s being taken as a number instead”. (I have this same worry with variadic functions in general, to be clear, as well as other helpful type system features.)
I kinda hate this suggestion but somewhat share the purity instincts that generated it :p
I think Haskell doesn’t really have anything analagous here. With typed lists and no variadic functions, there’s not much need for it. And I think all the approaches to variadic functions I looked at here, still need the number of arguments to be known at compile time.
I’d just write it informally, as something like ”
(+ a_1 ... a_n b_1 ... b_m) == (+ (+ a_1 ... a_n) (+ b_1 ... b_m))
forn, m >= 0
”See also:
I don’t consider this valuable[1]. I think it should instead be:
...or whatever ‘a function call with zero arguments’ is in this language. (I’m assuming
(f)
means ‘call f with zero arguments’).Mainly because there’s no way to have multiple associative functions with the same zero element that doesn’t compromise on some identity otherwise.
Well, in standard Hindley-Milner, there’s no such thing. Every function takes one argument and returns a value, which might itself be a function.
It’s conceivable that some extension could change that, and yeah, syntactically distinguish between
+
the variadic function, and(+)
the result of passing no arguments to+
. I don’t think any of the schemes listed in this post would make that distinction though. The Zip Calculus’ version of “passing no arguments” would be “passing an empty tuple”. The typeclass approach would distinguish them by typechecking, and I think Infinitary Tuples would too.I keep forgetting standard HM is that restrictive.