What do the empty parentheses `()` mean in Elm?

谁说我不能喝 提交于 2019-12-08 15:35:21

问题


I found out they are mean an empty tuple. However, are they also used as a convention by Elm programmers to mean "value can be ignored"?

is13 : Int -> Result String ()
is13 code =
  if code == 13 then Ok () else Err "not the right key code"

Source: https://github.com/pdamoc/elmChallenges/blob/master/challenge5.elm


回答1:


The empty parentheses () are what's known as a unit type, that is, a type that can only ever have a single value. A tuple type with at least one item can have any number of values (for example, a type defined as a tuple of one Int could have an infinite number of values, from (-∞) to (+∞)). But how many possible values of "the empty tuple" are there? Just one, hence why it's called a unit type.

The value of a unit type is that you can use it in places where other languages would have a null or void type, while avoiding the problems that null carries with it. For example, as you've noticed, it's often used in places where you want to say "I don't care what the value is". But there is a value there; it's not the absence of a value.

This has many advantages; for example, you can say "ALL functions return a value", and this will be true. Sometimes the value is one you don't care about, but all functions will return a value. In languages with a void type, you can't say that. For example, C# has two different ways to declare a function delegate: Func<T> for a function returning type T, and Action for a function returning void. In Elm (and F#, and other functional languages that use a unit type), there's no need for that distinction: all functions return a value, so all functions could be treated as the equivalent of Func<T>. Sometimes type T is the empty tuple, but it means that you don't have to write two versions of, say, map.

Another advantage is that it lets you compose functions more easily. Here's an example taken from the Wikipedia page on unit types. In C, you can't do this:

void f(void) {}
void g(void) {}

int main(void)
{
  f(g()); // compile-time error here
  return 0;
}

This is an error, because you're not allowed to pass void as a parameter: it's the absence of a value. Which means that you can't use standard function composition to chain functions f and g together. But here's another snippet from the same article, of C++ this time, showing what it would look like if you gave C++ an Elm-like unit type:

class unit_type {};
const unit_type the_unit;

unit_type f(unit_type) { return the_unit; }
unit_type g(unit_type) { return the_unit; }

int main()
{
  f(g(the_unit));
  return 0;
}

Now, because g returns a real value (even though it's one you don't care about), you can compose f and g meaningfully. This makes your program more elegant and easy to read in the long run.

Some further reading that might help you:

  1. https://en.wikipedia.org/wiki/Unit_type (which I've already linked once in this answer)
  2. Why do I need to use the unit type in F# if it supports the void type?

Hope this helps!



来源:https://stackoverflow.com/questions/33949145/what-do-the-empty-parentheses-mean-in-elm

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!