2012-01-04 9 views
30

¿Cómo importo explícitamente las instancias de clase de tipo? Además, ¿cómo hago esto con una importación calificada?Importación explícita de instancias

Actualmente, estoy haciendo

import Control.Monad.Error() 

importar la instancia mónada que puedo usar para (Either String). Anteriormente, he utilizado

import Control.Monad.Error 

No estoy satisfecho con cualquiera de los dos, porque la instancia Monad ha sido importada de manera implícita.

Respuesta

45

La incapacidad de controlar las importaciones de instancias es una de las compensaciones que hace el sistema de clase de tipo Haskell. He aquí un ejemplo de una hipotética dialecto Haskell donde puede:

Foo.hs:

module Foo where 

data Foo = FooA | FooB deriving (Eq, Ord) 

Bar.hs:

module Bar (myMap) where 

import Data.Map (Map) 
import qualified Data.Map as Map 

import Foo 

myMap :: Map Foo Int 
myMap = Map.singleton FooA 42 

Baz.hs:

module Baz where 

import Data.Map (Map) 
import qualified Data.Map as Map 

import Foo hiding (instance Ord Foo) 
import Bar (myMap) 

instance Ord Foo where 
    FooA > FooB = True 
    FooB > FooA = False 

ouch :: Map Foo Int 
ouch = Map.insert FooB 42 myMap 

¡Yikes! El conjunto myMap se creó con el instance Ord Foo adecuado, pero se está combinando con un mapa creado con diferente, instancia contradictoria.

Ser capaz de hacer esto violaría la suposición del mundo abierto de Haskell. Desafortunadamente, no conozco un buen recurso centralizado para aprender sobre él. Este section of RWH podría ser útil (busqué "la suposición del mundo abierto de Haskell").

+0

Mapas, no conjuntos. Buen ejemplo, +1. –

+0

@DanielFischer: Corregido, gracias :) – ehird

+3

Lo que significa, que si quieres ir por ese camino, deberías hacer instancias de primera clase, para que un Mapa pueda llevar su diccionario Ord alrededor? –

7

No puede. Las instancias siempre se exportan implícitamente y, por lo tanto, no puede importarlas explícitamente. Por cierto, la instancia Either e de Monad está actualmente en Control.Monad.Instances.

2

Aunque la respuesta general correcta sería: "no, no se puede", que sugieren esta solución horrendo:

copia + pega

Tome un vistazo al código fuente de la biblioteca para la deseada módulo, y copie/pegue las declaraciones de datos necesarias, las importaciones y las definiciones de funciones en su propio código. No copie las instancias que no desea.

Dependiendo del problema que nos ocupa, la ghc type system extensionsOverlappingInstances o IncoherentInstances podría ser una solución alternativa, aunque esto probablemente no va a resolver ningún problema con las bibliotecas base.

+1

Creo que Matt quería poder decir algo como 'import Foo (instancia Bar Baz)' que 'import Foo (barra, instancia oculta Baz)'. –

+0

@DanielFischer - bueno, sí. Sin embargo, en la ausencia de poder hacer eso, si es absolutamente necesario hacer tal cosa, copiar y pegar es la única solución del "plan B" que podría pensar. También podría ser bueno agregar un comentario como '{- # ThisInstanceTrumps # -}' para forzar a GHC a usar su instancia en lugar de cualquier instancia que de otro modo podría elegir. –

+4

Guau, esta es realmente una sugerencia horrible. Lo único que se omite es usar 'unsafeCeroer' para la interoperación entre los originales y sus definiciones de copia/pegado. –

Cuestiones relacionadas