Вы, вероятно, не можете дать go
сигнатуру типа как есть.
Причина этого в том, что она использует полиморфные аргументы, связанные с test
.Это означает, что внутри go
идентификатор f
имеет тип (ao -> ai)
для некоторых конкретных, но неизвестных типов ao
и ai
.
Переменные типа обычно являютсятолько в области действия для сигнатуры одного типа, в которой они представлены, поэтому, когда вы присваиваете go
собственную сигнатуру типа, ao
и ai
появляются новые полиморфные типы, которые, конечно, вызывают ошибку типа при попыткеобъединить их с одноименными, но фиксированными (и непознаваемыми) типами из сигнатуры test
.
Конечным результатом является то, что вы не можете написать тип go
явно, что не являетсяочень сытноЧтобы решить эту проблему, GHC предлагает расширение ScopedTypeVariables, которое позволяет помещать переменные, введенные в сигнатуру типа, в контекст внутри предложения where
функции, среди прочего.
Обратите внимание, что есливы используете только предложение where
для создания внутренней области видимости для определений и не используете идентификаторы, связанные аргументами с внешней функцией, вы можете писать сигнатуры типов в предложении where
так же, как вы можете для верхнего уровняпривязок.Если вы не хотите использовать расширения GHC, вы можете просто передать параметры избыточно.Примерно так должно работать в таком случае:
test :: Monad m => (ao -> ai) -> Iteratee ai m b -> Iteratee ao m b
test f iter = go f $$ iter
where go :: Monad m => (ao -> ai) -> Step ai m b -> Iteratee ao m b
go f (Continue k) = continue $
\stream -> go f $$ k (fmap f stream)
go _ (Yield res _) = yield res EOF