2010-03-24 4 views
2

При попытке скомпилировать следующий код, который представляет собой усовершенствованную версию read build на readMay из Safe package.Ошибка «переменная неоднородного типа» при определении пользовательской функции «чтение»

readI :: (Typeable a, Read a) => String -> a 
readI str = case readMay str of 
       Just x -> x 
       Nothing -> error ("Prelude.read failed, expected type: " ++ 
           (show (typeOf > (undefined :: a))) ++ 
           "String was: " ++ str) 

я получаю ошибку от GHC:

WavefrontSimple.hs: 54: 81:
Неопределенный тип переменной `а 'в ограничении:
` типируемых а'
, вытекающие из использование `typeOf 'в src/WavefrontSimple.hs: 54: 81-103
Вероятное исправление: добавьте сигнатуру типа, которая исправляет эти переменные типа`

Я не понимаю, почему. Что нужно исправить, чтобы понять, что я имел в виду?

EDIT: Ok, поэтому решение использовать ScopedTypeVariables и forall a в типе подписи работ. Но почему следующее приводит к очень похожей ошибке с той, что была выше? Компилятор должен вывести правильный тип, поскольку используется asTypeOf :: a -> a -> a.

readI :: (Typeable a, Read a) => String -> a 
readI str = let xx = undefined in 
      case readMay str of 
       Just x -> x `asTypeOf` xx 
       Nothing -> error ("Prelude.read failed, expected type: " 
           ++ (show (typeOf xx)) ++ 
           "String was: " ++ str) 
+0

Я проголосовал за закрытие, как обман перед редактированием. Теперь, когда вопрос был обновлен, я считаю, что он больше не является дубликатом, но не может удалить VTC. Думаю, мне просто придется ждать, пока он истечет сам по себе. – ephemient

ответ

2

последний не работает, так как тип xx такой же, как тип undefined - то есть, «FORALL а а..» Тот факт, что вы вынуждаете xx использовать один конкретный тип с помощью оператора asTypeOf, не означает, что он менее полиморфен везде.

+0

Я считаю, что вы правы. Мое понимание до вашего объяснения было немного иным, и мне еще предстоит изменить свое мышление. – Tener

1

Мне кажется, вам нужны переменные типа.

{-# LANGUAGE ScopedTypeVariables #-} 
readI :: forall a. (Typeable a, Read a) => String -> a 
readI str = case readMay str of 
       Just x -> x 
       Nothing -> error ("Prelude.read failed, expected type: " ++ 
           (show (typeOf > (undefined :: a))) ++ 
           "String was: " ++ str) 

See also.

+0

Упс, я должен был сначала искать дубликаты. Это очевидно одно. – ephemient

+0

Я искал дубликаты, по-видимому, недостаточно жесткие. Виноват. – Tener

2

a в undefined :: a и readI :: (Typeable a, Read a) => String -> a не то же самое типаa. Это как если бы вы написали readI :: ... a; readI = ... (undefined :: b).

{-# LANGUAGE ScopedTypeVariables #-} 

readI :: forall a. (Typeable a, Read a) => String -> a 
... 

Расширение scoped type variables изменяет язык Haskell, чтобы позволить вам нести тип переменнойa из внешней области во внутреннюю сферу, если явно количественно forall.


Я не знаю, почему ваша x `asTypeOf` xx не похоже на работу. Это делает, хотя:

readI :: (Typeable a, Read a) => String -> a 
readI str = xx where 
    xx = case readMay str of 
      Just x -> x 
      Nothing -> error ("Prelude.read failed, expected type: " 
           ++ (show (typeOf xx)) ++ 
           "String was: " ++ str) 
+0

Этот вопрос может быть обманом, но это лучшее объяснение, которое я видел до сих пор. –

Смежные вопросы