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