2012-02-04 25 views
7

Empecé a estudiar Haskell hace una semana y tengo un problema extraño. Creé un tipo de datos simple y quiero mostrarlo en una consola. Creé 2 funciones para 2 constructores de mi tipo. El compilador puede llamar a la función si uso un constructor con 2 argumentos. Pero no puede llamar a otra función que atrape un constructor con 1 argumento.Funciones para diferentes constructores de datos

module Main (
    main 
) where 

data MyContainter a b = FirstVersion a b 
        | SecondVersion a 
        deriving(Show,Eq) 

showContainer (FirstVersion a b) = show b 
showContainer (SecondVersion a) = show a 

--startF = showContainer (FirstVersion 1 2) -- it works 
startF = showContainer (SecondVersion 1) -- it doesn't work 

main = putStr startF 

Los compiladores dice:

Ambiguous type variable `a0' in the constraint: 
    (Show a0) arising from a use of `showMaybe' 
Probable fix: add a type signature that fixes these type variable(s) 
In the expression: showMaybe (SecondVersion 1) 
In an equation for `startF': startF = showMaybe (SecondVersion 1) 

¿Por qué dice eso? Creé (SecondVersion 1) directamente y no entiendo por qué el compilador no llama a showContainer (SecondVersion a).

+0

Ayuda a darse cuenta de que la variable de tipo 'a0' en el mensaje de error es igual que' b', y no tiene nada que ver con 'a'. (El compilador simplemente eligió ese nombre porque la clase 'Show' usa el nombre' a'). – hammar

Respuesta

9

El problema es que tiene showContainer del tipo:

showContainer :: (Show a, Show b) => MyContainer a b -> String 

Pero cuando se pasa SecondVersion 1, que no sabe lo que es b, porque SecondVersion 1 obras para cualquier tipo de b! Cuando pasa un FirstVersion, funciona bien, porque, como FirstVersion contiene un a y un b, nunca hay ambigüedad en cuanto a lo que deberían ser.

Por lo tanto, ya que el compilador no tiene forma de saber lo que b desea, y no hay manera de saber que la elección de b no afecta showContainer (después de todo, no afectar el comportamiento cuando se pasa FirstVersion, ya que usa show en un valor de tipo b), se da por vencido.

Eso es lo que el mensaje de error que dice: el tipo de variable a0 es ambigua, así que por favor añadir una firma tipo de decirme lo que es. En este caso, no importa lo que es, lo que sólo puede configurarlo para que ():

startF = showContainer (SecondVersion 1 :: MyContainer Integer()) 

Es probable que no se encontrará con errores como este muy a menudo, ya que el contexto se utilizan los valores de usualmente forzará que se use un b específico.

Desafortunadamente, GHC no es el mejor en la selección de variables de tipo; si le diste a showContainer una firma de tipo explícita como la que mostré, entonces usaría b también en el mensaje de error.

+0

Gracias, esa es una bonita descripción) – Alexey

Cuestiones relacionadas