Означает ли «ограничение значений», что функционального программирования более высокого порядка не существует?
Абсолютно нет! Ограничение значений практически не мешает функциональному программированию высшего порядка. То, что делает , ограничивает некоторые применения полиморфных функций & mdash; not функций высшего порядка & mdash; на верхнем уровне.
Давайте посмотрим на ваш пример.
Ваша проблема в том, что oops
и oops2
являются функцией идентификации и имеют тип forall 'a . 'a -> 'a
. Другими словами, каждый является полиморфным значением. Но правая часть не является так называемым «синтаксическим значением»; это функциональное приложение. (Приложению-функции не разрешено возвращать полиморфное значение, потому что в противном случае вы могли бы создать взломанную функцию, используя изменяемые ссылки и списки, которые могли бы подорвать систему типов; то есть вы могли бы написать тип завершающей функции типа forall 'a 'b . 'a -> 'b
.
К счастью, почти во всех практических случаях рассматриваемое полиморфное значение является функцией, и вы можете определить ее с помощью расширения eta:
let oops x = simple "" x
Эта идиома выглядит так, как будто у нее есть некоторые затраты времени выполнения, но в зависимости от встроенного модуля и оптимизатора, от которых может избавиться компилятор - это просто плохая проверка типов, которая испытывает проблемы.
Пример oops2
более проблематичен, потому что вы должны упаковать и распаковать конструктор значений:
let oops2 = F(fun x -> let F f = get "" in f x)
Это довольно утомительно, но анонимная функция fun x -> ...
является синтаксическим значением, а F
является конструктором типа данных, а конструктор, примененный к синтаксическому значению, также является синтаксическим значением, и Боб - ваш дядя , Упаковка и распаковка F
будут скомпилированы в функцию идентификации, поэтому oops2
собирается скомпилировать в точно тот же машинный код, что и oops
.
Все еще хуже, если вы хотите, чтобы вычисления во время выполнения возвращали полиморфное значение, например None
или []
. Как намекнул Натан Сандерс, вы можете столкнуться с ограничением значения с помощью простого выражения rev []
:
Standard ML of New Jersey v110.67 [built: Sun Oct 19 17:18:14 2008]
- val l = rev [];
stdIn:1.5-1.15 Warning: type vars not generalized because of
value restriction are instantiated to dummy types (X1,X2,...)
val l = [] : ?.X1 list
-
Ничего более высокого порядка там нет! И все же действует ограничение стоимости.
На практике ограничение значения не представляет препятствия для определения и использования функций более высокого порядка ; ты просто эта-расширяйся.