Предположим, у меня есть составной тип данных -
data M o = M (String,o)
Теперь я могу определить функцию, которая работает для ВСЕХ M
независимо от или
. Например -
f :: M o -> M o
f (M (s,o)) = M (s++"!", o)
Однако f
на самом деле не такой общий, как хотелось бы. В частности, использование f
в выражении фиксирует тип o
, поэтому я не могу снова использовать f
с другим типом o
. Например, в следующем примере не выполняется проверка типов -
p f = undefined where
m1 = M ("1", ())
m2 = M ("2", True)
m1' = f m1
m2' = f m2
Это вызывает ошибку - Не удалось сопоставить ожидаемый тип 'Bool' с фактическим типом '()'
Удивительно, но если я не предоставлю f в качестве аргумента а вместо этого просто используйте глобальное определение f, тогда оно компилируется и отлично работает! т.е. это компилирует -
p = undefined where
m1 = M ("1", ())
m2 = M ("2", True)
m1' = f m1
m2' = f m2
Есть ли для этого особая причина? Как я могу обойти эту проблему, т.е. определить функцию f
, которая может применяться ко всем (M o)
, даже когда o
изменяется в пределах одного и того же выражения ? Я предполагаю, что здесь в игру вступают экзистенциальные типы, но я просто не могу понять, как это сделать.