Итак, у меня есть класс:
class C a where
reduce :: a -> Int
Теперь я хочу упаковать его в тип данных:
data Signal = forall a. (C a) => Signal [(Double, a)]
Благодаря экзистенциальной квантификации я могу вызывать методы C для сигналов, но сигналы не выставляют параметр типа:
reduceSig :: Signal -> [(Double, Int)]
reduceSig (Signal sig) = map (second reduce) sig
Теперь, поскольку C имеет ряд методов, моим естественным следующим шагом является вытащить функцию "уменьшить", чтобы я мог заменить любой метод:
mapsig :: (C a) => (a -> a) -> Signal -> Signal
mapsig f (Signal sig) = Signal (map (second f) sig)
Введите ошибку! Не удалось вывести (a1 ~ a). Дальнейшая мысль, я думаю, что это говорит о том, что 'f' является функцией в некотором экземпляре C, но я не могу гарантировать ему тот же экземпляр C, что и в Сигналах, потому что параметры типа скрыты! Я хотел этого, я понял.
Значит ли это, что невозможно обобщить reduceSig? Я могу жить с этим, но я настолько привык к тому, чтобы свободно разлагать функции в haskell, и странно, что он обязан писать шаблон. С другой стороны, я не могу придумать никакого способа выразить, что тип равен типу внутри Сигнала, не давая Сигналу параметр типа.