2010-05-21 21 views
16

Suena tonto, pero no puedo entenderlo. ¿Por qué la expresión [] == [] se puede escribir? Más específicamente, ¿qué tipo (en la clase Eq) se deduce del tipo de elementos de lista?¿Cómo es el tipo de `([] ==) []` inferido haskell?

En una sesión ghci, veo lo siguiente:

Prelude> :t (==[]) 
(==[]) :: (Eq [a]) => [a] -> Bool 

Pero la restricción Eq [a] implica Eq a también, como se muestra aquí:

Prelude> (==[]) ([]::[IO()]) 

<interactive>:1:1: 
No instance for (Eq (IO())) 
    arising from use of `==' at <interactive>:1:1-2 
Probable fix: add an instance declaration for (Eq (IO())) 
In the definition of `it': it = (== []) ([] :: [IO()]) 

Así, en [] == [] , el verificador de tipos debe asumir que el elemento de lista es de algún tipo a que está en la clase Eq. ¿Pero cual? El tipo de [] es solo [a], y esto es ciertamente más general que Eq a => [a].

mi humilde opinión, esto debería por ambigua, al menos en Haskell 98 (que es lo que estamos hablando)

+3

Con GHC (no GHCi) tengo 'Variable de tipo ambiguo \ 'a' en la restricción \ 'Eq a' que surge de un uso de \ '== '' – kennytm

+0

@Kenny - sí, eso es lo que esperaba antes de probar en ghci - mayor es mi sorpresa. Gracias por la pista, ahora mi orden mundial está restaurada :) – Ingo

+0

Es interesante Abrazos da la expresión '[] == []' tipo 'Eq a => Bool'. – sdcvvc

Respuesta

19

GHCi tiene extended rules for type defaulting, que es lo que te hizo tropezar. En este caso, creo que dejaría el tipo ambiguo predeterminado en (). Las maneras sutiles en que GHCi se comporta de manera diferente son agradables por el bien de una mejor interactividad, pero a veces ocasionan confusión ...

+8

@camccann: ejecuta 'ghci -Wall'. entonces '[] == []' obtiene 'Advertencia: Incumplir la (s) siguiente (s) restricción (es) para escribir '()' ' – yairchu

+1

El incumplimiento prolongado solo importa cuando se desea mostrar o ejecutar el código. El :: (Eq a) => [a] -> tipo Bool es completamente correcto. –

+1

@Don Stewart: Ese tipo es, por supuesto, correcto. Creo que lo que confundió a Ingo es más bien '([] == []) :: Bool', donde la restricción ambiguo' Eq a' se cumple por defecto a '() ', como yairchu demostró. –

1

GHC infiere el tipo más general:

(== []) :: (Eq a) => [a] -> Bool

debe leerse como:

  • si tiene una instancia de una ecuación,
  • continuación, Haskell le puede dar una función de las listas de los 'un es a Bool

Así que sí, la implicación aquí es que usted tiene una instancia de la ecuación para los elementos de la lista, y GHC ya tiene una instancia para las listas en general (confiando en Eq para los elementos), así obtenemos un buen tipo general.

El comprobador de tipos "asume" que puede proporcionar una instancia de Eq cuando se llama a un tipo en particular.

No puedo reproducir los resultados de tener una restricción de Eq [a].

+0

aunque Kenny arriba obtuvo diferentes resultados con GHC. Nota: Estamos hablando de Haskell 98, estoy seguro de que algunas lujosas extensiones de GHC son lo suficientemente inteligentes como para escribirlo correctamente, sin embargo, todavía no entiendo cómo exactamente. En mi humilde opinión, este es realmente un caso ambiguo. – Ingo

+1

@Ingo: '(== [])' no es ambiguo, solo polimórfico como de costumbre; funcionará igual (y correctamente) en GHCi o de otra manera. En cuanto a las extensiones de GHC, puede habilitar el mismo incumplimiento extendido que utiliza GHCi, pero no sé por qué querría ... –

+0

@Don: ¿Quizás tenga diferentes versiones/indicadores?En cuanto a mí: X: \ fc3> ghci ___ ___ _ /_ \/\/\/__ (_) // _ \ ///_///| | GHC Interactive, versión 6.4.2, para Haskell 98. // _ \\/__// ___ | | http://www.haskell.org/ghc/ \ ____/\// _/\ ____/| _ | Tipo :? por ayuda Cargando el paquete base-1.0 ... vinculando ... hecho. Preludio>: t (== []) (== []) :: (Eq [a]) => [a] -> Bool Preludio> – Ingo

Cuestiones relacionadas