В this работе SPJ, на странице 3 и 4, написано:Возможно совпадение совпадений функций на уровне типа, но не на уровне значений, почему это различие?
class Mutation m where
type Ref m :: * -> *
newRef :: a -> m (Ref m a)
readRef :: Ref m a -> m a
writeRef :: Ref m a -> a -> m()
instance Mutation IO where
type Ref IO = IORef
newRef = newIORef
readRef = readIORef
writeRef = writeIORef
instance Mutation (ST s) where
type Ref (ST s) = STRef s
newRef = newSTRef
readRef = readSTRef
writeRef = writeSTRef
и:
Объявление класса в настоящее время представляет тип функции Ref (с указанного вида) наряду с обычные функции значений, такие как newRef (каждый с указанным типом). Аналогично, каждое объявление экземпляра вносит предложение, определяющее функцию типа в типе экземпляра , рядом с свидетелем для каждой функции значения.
Мы говорим, что Ref является типом семейства или связанным типом класса Mutation. Он ведет себя как функция на уровне уровня, поэтому мы также вызываем Ref функцию типа. Применение функции типа использует тот же синтаксис, что и применение конструктора типа : Ref m a выше означает применить функцию типа Ref to m, , затем применить полученный конструктор типа к a.
То есть, другими словами,
Ref :: (*->*)->*->*
, который, Ref
принимает функцию уровня типа в качестве аргумента, как Maybe
или IO
или []
и производит другую функцию уровня типа, такие, как IORef
использованием a соответствие шаблону, т.е. Ref
определяется знаком .
Итак, как возможно, что можно сопоставлять шаблоны с функциями на уровне типа, но не на уровне значений?
Например,
fun2int:: (Int->Int)->Int
fun2int (+)=2
fun2int (*)=3
не возможно писать, потому что равенство на функциях является undecidable.
1) Так как же возможно, что на уровне типа это не вызывает проблем?
2) Это потому, что функции на уровне типа имеют очень ограниченный вид? Таким образом, никакая функция на уровне уровня не может быть аргументом Ref
, только несколько выбранных, а именно те, которые объявлены программистом, а не такие функции, как (+), которые являются более общими, чем те, которые были объявлены программистом? Является ли это причиной того, что при сопоставлении шаблонов функций уровня типа нет проблем?
3) Является ли ответ на этот вопрос связанным с this частью спецификации GHC?
Хороший вопрос. Основная причина - (2). Например, вы не можете передавать частично прикладное семейство типов в другое семейство типов, которое было бы очень мощным и создавало бы неразрешимость. Вы можете сопоставлять шаблоны только для конструкторов типов, которые никогда не приводят к сокращению. – luqui
Спасибо luqui, не могли бы вы объяснить это более подробно? Я не совсем понимаю, что вы подразумеваете под сокращением. – jhegedus
«Согласование шаблонов» по типам, выполняемым унификацией - объединение двух типов является разрешимой процедурой, типы просто сравниваются структурно, а затем номинально, чтобы решить, являются ли они равными. С другой стороны, функции уровня ценности не имеют такой процедуры для вывода, если они равны (за исключением сравнения всех входов и выходов - которые слишком медленны, чтобы быть даже близкими к практическим). Если вы объявите два идентичных типа Maybe, компилятор будет настаивать на том, что они различны (по праву), но в гипотетическом мире с равенством функций это, вероятно, будет очень неожиданным поведением. – user2407038