2015-03-20 3 views

ответ

6

Вам необходимо включить расширение 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.

+1

В этом случае вы не могли бы избежать расширений, отбросив подпись типа? Конечно, это будет довольно сложно понять. – dfeuer

+0

@dfeuer Я пропустил это, спасибо! Я обновился, чтобы упомянуть об этом. – chi

+0

Я лично считаю, что подход «ScopedTypeVariables» является лучшим. – dfeuer