2010-09-08 3 views
5

Продолжающиеся контрольно-пропускные пункты при попытке изучить Haskell.Ошибка сборки GHC, возникающая из-за импорта Control.Exception

Я следую «Real World Haskell», а когда дело доходит до получения одного из своих сложных примеров на работу, я получаю следующую ошибку

«Неопределенный тип переменной e' in the constraint: GHC.Exception.Exception е» , возникающие в связи с использованием `ручки» в FoldDir.hs: 88: 14-61 Возможная ошибка: добавить сигнатуру типа, который фиксирует эти типа переменной (ы)»

Мои соответствующие биты кода являются:

import Control.Exception (bracket, handle) 
maybeIO :: IO a -> IO (Maybe a) 
maybeIO act = handle (\_ -> return Nothing) (Just `liftM` act) 

Как устранить эту ошибку?

+0

Возможный дубликат: http://stackoverflow.com/questions/431527/ambiguous-type-variable-error-msg –

ответ

14

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

Вы можете сделать это, называя функция

import Control.Exception (handle, SomeException) 
maybeIO act = handle handler (Just `liftM` act) 
    where handler :: SomeException -> IO (Maybe a) 
      handler _ = return Nothing 

Или с помощью расширения ScopedTypeVariables:

{-# LANGUAGE ScopedTypeVariables #-} 
import Control.Exception (handle, SomeException) 
maybeIO act = handle (\(_ :: SomeException) -> return Nothing) (Just `liftM` act) 
+1

Это дает мне как ответ, так и помогает в моих попытках узнать и понять Haskell. –

1

Control.Exception предоставляет другой интерфейс в GHC 6.10 и позже. Для быстрого решения, изменить

import Control.Exception (bracket, handle) 

в

import Control.OldException (bracket, handle) 
1

Control.OldException устарела. С расширяемыми исключениями необходимо указать тип исключения, даже если он никогда не используется. Моя версия maybeIO является

perhaps ∷ forall a. IO a → IO (Maybe a) 
perhaps task = do 
    result ← (try ∷ IO a → IO (Either IOException a)) task 
    return $ either (const Nothing) Just result 

Нужно явное forall привести тип переменной a в область видимости, и флаг компилятора GHC -XExplicitForAll использовать явную forall. Нельзя дать try тип в открытом виде без получения ошибки «Вы не можете указать подпись типа для импортированного значения». Если вы попробуете объявление типа в другом месте, например. по результату try task, тогда GHC не может разобраться. Так что да, это немного неловко для нас, сильных адвокатов, но это становится лучше.