2011-12-26 22 views
14

estoy usando GHCi 7.0.3 con el siguiente programa que implementa la lista de nivel Tipo:XTypeOperators no funciona como pragma

{-# LANGUAGE TypeOperators #-} 

data True 
data False 

-- List 
data Nil 
data Cons x xs 

-- Type-level infix operator must begin with ':' 
data x ::: xs 
infixr 5 ::: -- set precedence level to 5 (tight) 

Compila, pero cuando lo pruebo con:

:t (undefined :: True:::Nil) 

(¿cuál es el tipo de undefined cuando se lanza a escribir True:::Nil?) me sale este error:

Illegal operator `:::' in type `True ::: Nil' 
    Use -XTypeOperators to allow operators in types 

Y de hecho, cuando comienzo GHCi con la bandera

-XTypeOperators 

puedo obtener el resultado esperado:

(undefined :: True ::: Nil) :: True ::: Nil 

Mi pregunta es: ¿Por qué no hace el trabajo equivalente pragma:

{-# LANGUAGE TypeOperators #-} 

Editar: Si los pragmas no se extienden al entorno GHCi que tengo otro acertijo. Probé este programa:

class And b1 b2 b | b1 b2 -> b where 
    andf :: b1 -> b2 -> b 

-- truth table 
instance And True True True where andf = undefined 
instance And True False False where andf = undefined 
instance And False True False where andf = undefined 
instance And False False False where andf = undefined 

Se requieren los siguientes pragmas:

{-# LANGUAGE MultiParamTypeClasses #-} 
{-# LANGUAGE FunctionalDependencies #-} 

Pero una vez compilado, pude utilizarlo en GHCi:

*Main> :t andf (undefined::True) (undefined::False) 
      andf (undefined::True) (undefined::False) :: False 

supongo que en el caso de la lista de la el intérprete ni siquiera podía analizar la expresión con el operador de nivel de tipo :::, mientras que en el caso de las clases de multiparámetros, la línea de comando era parseable. Pero, pensándolo bien, GHCi realizó la inferencia de tipos utilizando clases de parámetros múltiples y dependencias funcionales, ¿no es así? Esta inferencia tipo se hace en GHCi, y no llamando a alguna función en el código compilado, ¿verdad?

Respuesta

14

Las otras respuestas son correctas acerca de habilitar la extensión en GHCi, ya sea desde el indicador GHCi o como un indicador al iniciar GHCi. Sin embargo, existe una tercera opción: puede crear un archivo .ghci que se cargará y ejecutará cada vez que inicie GHCi, y lo usará para habilitar la extensión automáticamente. Particularmente para cosas como TypeOperators, donde hay muy poco daño en tenerlo habilitado, es muy conveniente.

Por ejemplo, esto es lo que se parece a la mía en este momento:

:set prompt "∀x. x ⊢ " 
:set -XTypeOperators 
import Control.Monad 
import Control.Applicative 
import Control.Arrow 

El archivo .ghci va en cualquier ubicación estándar de su sistema es para este tipo de archivos.


Para responder a su pregunta extendida: El código en cuestión trabaja en GHCi más o menos, ya que también podría funcionar si se utiliza en otro módulo, que importa el módulo usando los pragmas pero no se les permite en sí. GHC es más que capaz de habilitar extensiones por módulo, incluso cuando las definiciones exportadas posiblemente no tengan sentido sin una extensión, o tengan tipos inferidos que lo requieran.

La distinción es un poco confusa en GHCi porque también pone en el alcance las definiciones no exportadas del módulo, pero en general cualquier cosa que funcione si se utiliza desde otro módulo también funcionará en el indicador GHCi.

+1

+1 para el archivo .ghci –

7

Su pragma es correcto; el problema es que está tratando de usarlo desde dentro de GHCi, que no hereda las extensiones del módulo cargado, pero pasa pasando las opciones que le ha dado a GHC para compilar los archivos que lista (que es por qué tiene el mismo efecto que el pragma).

Debe mantener el pragma, y, o bien pasar -XTypeOperators cuando se inicia GHCi, o activarlo después de cargar el archivo de la siguiente manera:

GHCi> :set -XTypeOperators 

que podría ser muy indeseable, y probablemente imposible en muchos casos, por ejemplo cargando módulos compilados.

4

El pragma LANGUAGE funciona para el archivo fuente, no se propaga al ghci -prompt. Como es posible tener pragmas conflictivos en múltiples archivos fuente de un proyecto, los pragmas fuente no pueden propagarse por defecto al ghci -prompt. Sería posible tener los pragmas de *module s efectivos en el prompt, no estoy seguro, pero creo que se pondera implementar eso, de todos modos, hasta ahora, no está implementado, por lo que necesita establecer las extensiones para ghci explícitamente.

Cuestiones relacionadas