Вам необходимо включить расширение ScopedTypeVariables
и использовать явные forall
S:
{-# ScopedTypeVariables #-}
f :: forall a b . (Enum a, Bounded a) => A a b -> [(a,b)]
f x = [(as,bs) | as <- [minBound :: a ..] , bs <- x somefunction as]
Без этого, в Haskell каждый тип подписи интерпретируется независимо от других. То есть a
в minBound :: a
не имеет никакого отношения к a
в подписью выше.
Если вы действительно хотите придерживаться каких-либо расширений, вы можете написать вспомогательную функцию вместо:
myBound :: Bounded a => A a b -> a
myBound x = minBound -- does not really depend on x
f :: (Enum a, Bounded a) => A a b -> [(a,b)]
f x = [(as,bs) | as <- [myBound x ..] , bs <- x somefunction as]
В данном конкретном случае, как @dfeuer указывает ниже, есть гораздо более простое решение , Мы можем просто удалить аннотацию типа на minBound
:
-- no extensions
f :: (Enum a, Bounded a) => A a b -> [(a,b)]
f x = [(as,bs) | as <- [minBound ..] , bs <- x somefunction as]
Это работает, потому что список постижение выводит пары (as,bs)
, поэтому Haskell можно увидеть, что as
должен иметь тип a
, и что minBound
должны быть одного и того же типа as
.
В этом случае вы не могли бы избежать расширений, отбросив подпись типа? Конечно, это будет довольно сложно понять. – dfeuer
@dfeuer Я пропустил это, спасибо! Я обновился, чтобы упомянуть об этом. – chi
Я лично считаю, что подход «ScopedTypeVariables» является лучшим. – dfeuer