Пустота в противоречии с Юнитом - PullRequest
8 голосов
/ 14 декабря 2009

Я хотел бы понять, в чем разница между этими двумя концепциями программирования. Первый представляет отсутствие типа данных, а во втором тип существует, но информации нет. Кроме того, я признаю, что модуль основан на теоретическом фундаменте функционального программирования, но я до сих пор не могу понять, как можно использовать примитив модуля (например, в программе на F #).

Ответы [ 2 ]

12 голосов
/ 14 декабря 2009

Тип устройства просто делает все более регулярным. В некоторой степени вы можете думать о каждой функции в F # как о том, что она принимает один параметр и возвращает один результат. Функции, которые не нуждаются ни в каких параметрах, фактически принимают «единицу измерения» в качестве параметра, а функции, которые не возвращают никаких результатов, возвращают «единицу измерения» в качестве результата. Это имеет множество преимуществ; во-первых, рассмотрим, как в C # вам нужно как множество делегатов «Func» для представления функций различных арностей, которые возвращают значения, так и множество делегатов «Action», которые не возвращают значения (потому что, например, Func<int,void> не законно - void нельзя использовать таким образом, поскольку это не совсем «настоящий» тип).

См. Также Типы функций F #: веселье с кортежами и карри

9 голосов
/ 14 декабря 2009

В функциональном программировании мы обычно говорим о сопоставлении входов и выходов. Это буквально означает сопоставление аргумента с его возвращаемым значением (ями). Но если что-то будет функцией в математическом / теоретико-теоретическом смысле, оно должно вернуть что-то . Значение void означает, что функция ничего не возвращает, что в этих терминах бессмысленно.

unit - функциональный ответ на void. По сути, это тип только с одним значением, (). Он имеет ряд применений, но вот простой. Допустим, у вас было что-то подобное на более традиционном императивном языке:

public static <T, U> List<U> map(List<T> in, Function<T, U> func) {
  List<U> out = new ArrayList<U>(in.size());
  for (T t : in) {
     out.add(func.apply(t));
  }
  return out;
}

Это применяет определенную функцию func к каждому элементу в списке, создавая новый список с типом вывода func. Но что произойдет, если вы передадите функцию, которая просто печатает свои аргументы? У нее не будет типа вывода, так что вы можете указать для U?

В некоторых языках передача такой функции нарушает этот код (как в C #, где вы не можете присвоить void универсальному типу). Вам придется прибегнуть к обходным решениям, таким как Action<T>, который может стать неуклюжим.

Здесь полезна концепция unit: it - это тип, но тот, который может принимать только одно значение. Это значительно упрощает такие вещи, как создание цепочек и компоновка, и значительно уменьшает количество особых случаев, о которых вам нужно беспокоиться.

...