Ответ 1
Насколько я знаю, полиморфная функция seq
плоха, потому что она ослабляет бесплатные теоремы или, другими словами, некоторые равенства, которые действительны без seq
, более не действуют с seq
. Например, равенство
map g (f xs) = f (map g xs)
выполняется для всех функций g :: tau -> tau'
, все списки xs :: [tau]
и все полиморфные функции f :: [a] -> [a]
. В принципе, это равенство означает, что f
может только изменять порядок элементов своего списка аргументов или отбрасывать или дублировать элементы, но не может изобретать новые элементы.
Честно говоря, он может изобретать элементы, так как он может "вставлять" в списки недопустимое вычисление/время выполнения, поскольку тип ошибки является полиморфным. То есть, это равенство уже ломается на языке программирования, таком как Haskell без seq
. Следующие определения функций предоставляют встречный пример для уравнения. В принципе, с левой стороны g
"скрывает" ошибку.
g _ = True
f _ = [undefined]
Чтобы исправить уравнение, g
должен быть строгим, т.е. он должен отображать ошибку в ошибку. В этом случае снова выполняется равенство.
Если вы добавите полиморфный оператор seq
, уравнение снова разрывается, например, следующее экземплярирование - это примерный пример.
g True = True
f (x:y:_) = [seq x y]
Если мы рассмотрим список xs = [False, True]
, то
map g (f [False, True]) = map g [True] = [True]
но, с другой стороны,
f (map g [False, True]) = f [undefined, True] = [undefined]
То есть вы можете использовать seq
, чтобы элемент определенной позиции списка зависел от определения другого элемента в списке. Равенство выполняется снова, если g
является полным. Если вас интересуют бесплатные теоремы, ознакомьтесь с свободным теоретическим генератором, который позволяет указать, рассматриваете ли вы язык с ошибками или даже язык с seq
. Хотя это может показаться менее практичным, seq
прерывает некоторые преобразования, которые используются для улучшения работы функциональных программ, например foldr
/build
слияние происходит в присутствии seq
. Если вас интересуют более подробно о свободных теоремах в присутствии seq
, ознакомьтесь с Свободные теоремы в присутствии seq.
Насколько я знаю, было известно, что полиморфный seq
прерывает определенные преобразования, когда он был добавлен к языку. Однако у африкативов есть и недостатки. Если вы добавите класс типа seq
, вам может потребоваться добавить в вашу программу множество ограничений типа типа, если вы добавите seq
где-нибудь вглубь. Кроме того, не было выбора опустить seq
, как уже было известно, что существуют утечки пространства, которые могут быть исправлены с использованием seq
.
Наконец, я могу что-то пропустить, но я не вижу, как будет работать оператор seq
типа a -> a
. Ключ seq
заключается в том, что он вычисляет выражение для выражения нормальной формы, если другое выражение оценивается, чтобы возглавить нормальную форму. Если seq
имеет тип a -> a
, то нет возможности сделать оценку одного выражения зависящей от оценки другого выражения.