«Настоящая» универсальная функция в Haskell

Предположим, у меня есть составной тип данных -

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 изменяется в пределах одного и того же выражения ? Я предполагаю, что здесь в игру вступают экзистенциальные типы, но я просто не могу понять, как это сделать.

14
задан Anupam Jain 19 August 2011 в 11:52
поделиться