Я каждый раз начинаю объяснять, почему так не работает — и сам не понимаю. Ведь для процедур есть типы наподобие T -> (). По идее, () должен быть самостоятельным типом. И тогда Select в примере выше должен возвращать sequence of ().
Проблемы тут две, но обе, как мне кажется, не фатальные. Первая: типа () нет. И потому sequence of () компилятору непонятно. Вторая: если такой тип разрешить, можно ли создавать значения такого типа и как они должны выглядеть? Это менее тривиальный вопрос. В Хаскеле аналогичный тип () имеет вполне законное единственное значение (). Может быть, ввести таковое и разрешить Select.
Может быть, есть другие пути узаконить тип sequence of ()… Например, сделать его подтипом () (это так, фантазия) ну и считать, что получается процедура. Конечно, всё это не ложится на .NET, где Select принимает Func, а функции, возвращающие void, это другой тип — Action. Ну тогда, может просто ввести отдельный метод расширения ForEach, который будет принимать процедуры (Action'ы)? Но только так, чтобы ему можно было передавать лямбда-процедуры. Это действительно приятней для части людей (мне в том числе), чем обычный foreach писать.
В функциональном программировании тип void хорошо известен и есть консенсус о том, что название это плохое, потому что тип void, исходя из теоретико-множественных соображений, должен быть одноэлементным типом, а не пустым. Так что в ФП он чаще называется unit type, а не void type (а пустой тип называется bottom, то есть минимальный элемент решётки типов по включению — он тоже используется, но для других целей). Смысл такой: не бывает функций в пустое множество (конструкция int -> void в таком смысле противоречива). А вот в одноэлементное — бывают, причём в связи с тем, что тип (множество) () содержит один элемент, то вполне допустим синтаксический сахар, позволяющий не указывать конкретное возвращаемое значение (оно очевидно). Так в C-подобных языках в void-функциях можно не писать return, а можно где-то в середине писать return. С точки зрения ФП (математики) логичней было бы писать return () (здесь () это единственное значение типа ()). Но в C этот один элемент типа void, который с точки зрения математики всё равно есть, почему-то нельзя называть — этим он похож (внезапно) на иудейского бога.
Из-за этих чисто религиозных соображений и получаются такие проблемы, как необходимость отдельно писать Select, отдельно ForEach. В ФП нет таких проблем и там и то, и то делается с помощью map.
Согласен. В принципе, можно сделать одноэлементный enum. В синтаксисе не получится, но в принципе можно.
Непонятно, что дальше с ним делать. Вот давайте считать, что этот enum определен так: