que promocionado objeto nombre columna campos ambiguos ambiguo ambiguedad ambigua haskell type-inference typeclass

haskell - promocionado - Mensaje de error variable de tipo ambiguo



la columna en field list es ambigua (5)

El tipo de Control.Exception.handle es:

handle :: Exception e => (e -> IO a) -> IO a -> IO a

El problema que está viendo es que la expresión lambda (/_ -> return "err") no es del tipo e -> IO a donde e es una instancia de Exception . ¿Claro como el barro? Bueno. Ahora voy a proporcionar una solución que en realidad debería ser útil :)

Sucede que en su caso e debe ser Control.Exception.ErrorCall ya que undefined usa un error que arroja ErrorCall (una instancia de Exception ).

Para manejar usos de undefined , puede definir algo como handleError :

handleError :: (ErrorCall -> IO a) -> IO a -> IO a handleError = handle

Es esencialmente un alias Control.Exception.handle con e corregido como ErrorCall que es lo que arroja el error .

Se ve así cuando se ejecuta en GHCi 7.4.1 :

ghci> handleError (/_ -> return "err") undefined "err"

Para manejar todas las excepciones, se puede escribir una función handleAll siguiente manera:

handleAll :: (SomeException -> IO a) -> IO a -> IO a handleAll = handle

La captura de todas las excepciones tiene las consecuencias descritas bien en este extracto de la documentación de Control.Exception :

Captura todas las excepciones

Es posible detectar todas las excepciones, utilizando el tipo SomeException :

catch f (/e -> ... (e :: SomeException) ...)

¡SIN EMBARGO, esto normalmente no es lo que quieres hacer!

Por ejemplo, supongamos que quiere leer un archivo, pero si no existe, continúe como si contenga "" . Es posible que sienta la tentación de atrapar todas las excepciones y devolver "" en el controlador. Sin embargo, esto tiene todo tipo de consecuencias indeseables. Por ejemplo, si el usuario presiona el control C en el momento justo, se capturará la excepción UserInterrupt y el programa continuará ejecutándose bajo la creencia de que el archivo contiene "" . De forma similar, si otro hilo intenta matar el hilo que lee el archivo, se ThreadKilled excepción ThreadKilled .

En su lugar, solo debe detectar exactamente las excepciones que realmente desea. En este caso, esto probablemente sería más específico que incluso "cualquier excepción IO"; un error de permisos probablemente también desee ser manejado de manera diferente. En cambio, probablemente quieras algo como:

e <- tryJust (guard . isDoesNotExistError) (readFile f) let str = either (const "") id e

Hay ocasiones en las que realmente necesita detectar cualquier tipo de excepción. Sin embargo, en la mayoría de los casos esto es solo para que pueda hacer un poco de limpieza; usted no está realmente interesado en la excepción en sí misma. Por ejemplo, si abre un archivo, quiere volver a cerrarlo, ya sea que el procesamiento del archivo se ejecute normalmente o genere una excepción. Sin embargo, en estos casos puede usar funciones como bracket , finally y onException , que en realidad nunca le pasan la excepción, pero solo llame a las funciones de limpieza en los puntos apropiados.

Pero a veces realmente necesitas detectar cualquier excepción, y realmente ver cuál es la excepción. Un ejemplo es en el nivel superior de un programa, es posible que desee detectar cualquier excepción, imprimirlo en un archivo de registro o en la pantalla, y luego salir con gracia. Para estos casos, puede usar catch (o una de las otras funciones de captura de excepciones) con el tipo SomeException .

Fuente: http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Exception.html#g:4

No creo que sea un error, pero estoy un poco desconcertado sobre por qué eso no funciona. Una pregunta extra es por qué menciona la variable e? No hay variable e.

Prelude> :m +Control.Exception Prelude Control.Exception> handle (/_-> return "err") undefined <interactive>:1:0: Ambiguous type variable `e'' in the constraint: `Exception e'' arising from a use of `handle'' at <interactive>:1:0-35 Probable fix: add a type signature that fixes these type variable(s) Prelude Control.Exception>

Aparentemente funciona bien en ghci 6.8, estoy usando 6.10.1.

Editar: he minimizado el código. Espero que tenga el mismo resultado tanto en 6.8 como en 6.10

class C a foo :: C a => (a -> Int)-> Int foo _ = 1 arg :: C a => a -> Int arg _ = 2 bar :: Int bar = foo arg

tratando de compilarlo:

[1 of 1] Compiling Main ( /tmp/foo.hs, interpreted ) /tmp/foo.hs:12:10: Ambiguous type variable `a'' in the constraint: `C a'' arising from a use of `arg'' at /tmp/foo.hs:12:10-12 Probable fix: add a type signature that fixes these type variable(s) Failed, modules loaded: none. Prelude Control.Exception>


Este problema aparece solo en GHC 6.10; no se puede duplicar en GHC 6.8 porque el tipo de handle es diferente:

: nr@homedog 620 ; ghci GHCi, version 6.8.2: http://www.haskell.org/ghc/ :? for help Loading package base ... linking ... done. Prelude> :m +Control.Exception Prelude Control.Exception> handle (/_ -> return "err") undefined "err" Prelude Control.Exception>

OK, tal vez pueda hacer esto finalmente. Creo que el problema no es la restricción de monomorfismo, sino que has tocado una instancia del problema de Leer / Mostrar: estás ofreciendo manejar algún tipo de excepción, en la nueva versión de `manejar, hay más de un tipo de excepción, y el tipo de esa excepción no aparece en su resultado. Por lo tanto, el compilador no tiene forma de saber qué tipo de excepción está tratando de manejar. Una forma de trabajar esto es elegir uno. Aquí hay un código que funciona:

Prelude Control.Exception> let alwaysError :: SomeException -> IO String; alwaysError = /_ -> return "err" Prelude Control.Exception> handle alwaysError undefined "err"

Por cierto, el uso de ejemplo de handle en la documentación de la biblioteca de GHC no se compila en 6.10. He archivado un informe de error.


Intente darle a su controlador el tipo SomeException -> IO x , donde x es un tipo concreto, por ejemplo

import Control.Exception let f _ = putStrLn "error" :: SomeException -> IO () in handle f undefined


La "excepción e" es probable a partir de la firma tipo de "manejar".

La documentación dice:

handle :: Exception e => (e -> IO a) -> IO a -> IO a

En GHC 6.8 solía ser diferente, lo que explicaría por qué no obtengo ese error.

handle :: (Exception -> IO a) -> IO a -> IO a

Parece que te encuentras con la restricción de monomorfismo. Ese "_" - Patrón debe ser monomórfico (que es con ghc 6.8) o explícitamente escrito. Una "solución alternativa" es poner el patrón en el lado izquierdo de una definición, donde constituye un "enlace de patrón simple" como se especifica en el Informe Haskell.

Prueba esto:

let f _ = return "err" handle f undefined

http://www.haskell.org/haskellwiki/Monomorphism_restriction


Una solución alternativa es usar Control.OldException en ghc 6.10. * En lugar de Control.Exception .