If a function takes two arguments, why is its type annotation f: a -> b -> c ?
It's by design, which this article covers very well.
Wouldn’t something like f: (a, b) -> c make more sense?
Well, f: (a, b) -> c is a type annotation for a function that takes one argument, a tuple of a, b.
This type annotation makes no assumptions about the concrete types. As such it's hard to tell if it makes sense to require a and b together prior to being applied.
It might seem like a silly question, but thinking about it, functions in Java and C# do exactly this, require all arguments at once in order to be applied. So if that's your background I'd say it's not such a strange question.
...
For my own understanding I prefer working with a more concrete example:
getDistance2d : Int -> Int -> Int -> Int -> Int
This function calculates the distance between 2 coordinates.
You might argue it's easier to deal with:
getDistance2d : (Int, Int) -> (Int, Int) -> Int
The X and Y of a coordinate belong together. So I'd say it's reasonable to apply them in a unified form. You could be more explicit about your intent using a composite type:
getDistance2d: Coordinate -> Coordinate -> Int
And if you really don't want any curried instances:
getDistance2d: (Coordinate, Coordinate) -> Int
But I find it hard to see the benefit of that. The arguments don't belong together like the X and Y components of a Coordinate. So why give up on the luxury of being able to curry?
Disclaimer: I know C# and a bit of Haskell, I googled to check if my examples make sense to an Elm programmer, correct me if I'm wrong.
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
It's by design, which this article covers very well.
Well,
f: (a, b) -> c
is a type annotation for a function that takes one argument, atuple of a, b
.This type annotation makes no assumptions about the concrete types. As such it's hard to tell if it makes sense to require a and b together prior to being applied.
It might seem like a silly question, but thinking about it, functions in Java and C# do exactly this, require all arguments at once in order to be applied. So if that's your background I'd say it's not such a strange question.
...
For my own understanding I prefer working with a more concrete example:
getDistance2d : Int -> Int -> Int -> Int -> Int
This function calculates the distance between 2 coordinates.
You might argue it's easier to deal with:
getDistance2d : (Int, Int) -> (Int, Int) -> Int
The X and Y of a coordinate belong together. So I'd say it's reasonable to apply them in a unified form. You could be more explicit about your intent using a composite type:
getDistance2d: Coordinate -> Coordinate -> Int
And if you really don't want any curried instances:
getDistance2d: (Coordinate, Coordinate) -> Int
But I find it hard to see the benefit of that. The arguments don't belong together like the X and Y components of a Coordinate. So why give up on the luxury of being able to curry?
Disclaimer: I know C# and a bit of Haskell, I googled to check if my examples make sense to an Elm programmer, correct me if I'm wrong.