DEV Community

Discussion on: Partial Application of Functions in Elm

Collapse
 
courier10pt profile image
Bob van Hoove • Edited

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.