2012-05-22 2 views
6

У меня есть функция, как показано ниже:функция не может совпадать с типом

foo :: Int -> a -> [a] 
    foo n v = bar n 
     where 
     bar :: Int -> [a] 
     bar n = take n $ repeat v 

с использованием отчета GHCI об ошибке:

Couldn't match type `a' with `a1' 
      `a' is a rigid type variable bound by 
       the type signature for foo :: Int -> a -> [a] at hs99.hs:872:1 
      `a1' is a rigid type variable bound by 
       the type signature for bar :: Int -> [a1] at hs99.hs:875:9 
    Expected type: [a1] 
     Actual type: [a] 
    In the expression: take n $ repeat v 
    In an equation for `bar': bar n = take n $ repeat v 

При удалении типа декларации бар, код может быть скомпилирован без ошибок. Итак, что это за тип объявления здесь? И почему происходит ошибка, потому что объявление типа bar более общее, чем определение bar (которое привязано к некоторому типу в foo)?

Спасибо за помощь!

ответ

9

The a в

foo :: Int -> a -> [a] 

и a в

bar :: Int -> [a] 

различные переменные типа с тем же именем.

Чтобы получить поведение, которое вы ожидаете, включите расширение ScopedTypeVariables (например, путем вставки {-# LANGUAGE ScopedTypeVariables #-} в верхней части исходного файла), и изменить тип подписи foo в

foo :: forall a. Int -> a -> [a] 

Когда ScopedTypeVariables не включена, то она, как если исходный код был написан так:

foo :: forall a. Int -> a -> [a] 
foo n v = bar n 
    where 
    bar :: forall a. Int -> [a] 
    bar n = take n $ repeat v 

это не правда, сказать, что GHCi implici tly использует ScopedTypeVariables, если вы не укажете аннотацию типа для bar.

Вместо этого аннотация, указанная вами для bar, конфликтует с типом ghci infers --- вы утверждаете, что bar имеет тип, который ghci знает, что он не может иметь.

Когда вы удаляете аннотацию типа, вы удаляете конфликт.

ScopedTypeVariables изменяет значение аннотаций типа, которые вы поставляете. Это не влияет на тип ghc.

+0

Спасибо за помощь! Как я уже сказал, если удалить объявление типа «bar», ghci может скомпилировать код, означает ли это, что ghci неявно использует ScopedTypeVariable для этого? – Orup

+0

быть более понятным, переменные типа области и удаление объявления типа «bar» могут скомпилировать код. просто интересно, делают ли они один и тот же трюк. – Orup

+0

Нет, они добираются до одного и того же скомпилированного кода, но они поступают по-другому. См. Мое редактирование. – dave4420