2011-12-15 16 views
11

Cuando se utiliza el intérprete GHC interactiva, es posible solicitar el tipo inferido de una expresión:¿Cómo selecciona GHCi los nombres para las variables de tipo?

Prelude> :t map 
map :: (a -> b) -> [a] -> [b] 

Parece que lleva los nombres de las variables de tipo de la firma desde el map es defined como

map :: (a -> b) -> [a] -> [b] 
map _ []  = [] 
map f (x:xs) = f x : map f xs 

en el preludio. ¡Eso tiene mucho sentido! Mi pregunta es: ¿cómo se seleccionan los nombres de las variables de tipo cuando no se da una firma?

Un ejemplo sería

Prelude> :t map fst 
map fst :: [(b, b1)] -> [b] 

donde recogió nombres b y b1. Está claro que el cambio de nombre debe tener lugar, sino simplemente a partir de a, b, ... habría dado

map fst :: [(a, b)] -> [a] 

lugar, que me parece un poco más legible.

Respuesta

13

Como yo lo entiendo, ghci elige nombres en el mismo orden que infiere los tipos. Se utiliza el esquema de nombres como usted ha mencionado para decidir el nombre del tipo del resultado, que es [b] porque ese es el nombre del tipo especificado en la definición de map. Luego decide que la función que es el primer parámetro para map debe devolver algo del tipo b también.

La variable de tipo restante para ser nombrado es por lo tanto la variable de tipo para el segundo elemento de la tupla argumento para fst, y de nuevo, se ve en la definición de fst para decidir qué nombre va a utilizar. La definición de fst :: (a, b) -> a, por lo b sería el nombre preferido aquí, pero desde b ya que se adopte, se anexa un 1 para que se convierta b1.

creo que este sistema tiene ventajas en situaciones en las que no se ocupan de tipos arbitrarios como es el caso aquí. Si el tipo de resultado se ve algo como esto, por ejemplo:

castAdd :: (Num n, Num n1, Num n2) => n -> n1 -> n2 

... podría decirse que es más fácil de leer que:

castAdd :: (Num a, Num b, Num c) => a -> b -> c 

... sobre todo porque puede confiar en que n# significa un valor numérico tipo, ya que la definición de clase para Num es class Num n where ....

EDITAR: Sí, sé que castAdd es imposible de implementar, pero es solo un ejemplo.

+1

Gracias, eso es una buena explicación! No había pensado en el caso en el que desea que se renombren varios 'n', pero siga relacionado. –

+0

No es imposible. (unSafeCoerce o simplemente viejo '_ | _') – PyRulez

Cuestiones relacionadas