2011-04-13 13 views
8

Tengo un viejo código Haskell que incluye casos de prueba QuickCheck. Las versiones más recientes de QuickCheck (Acabo de actualizar a 2.4.0.1) incluyen instancias de clase de tipo para Arbitrary Word8 y otros. Estos no existían en las versiones 2.0.x anteriores de Test.QuickCheck.Arbitrary.¿Cómo se anulan las instancias de clase de tipo Haskell proporcionadas por el código del paquete?

Si bien es útil en el sentido general, la Arbitrary Word8 generador de paquetes proporcionada no es el que yo quiero usar para mi banco de pruebas:

instance Arbitrary Word8 where 
    arbitrary = frequency [(2, oneof [return ctrlFrameDelim, return ctrlEscape, return ctrlXon, return ctrlXoff]), 
         (8, choose (0, 255))] 

El código anterior produce un error en la declaración instancia duplicada en tiempo de compilación . Puedo sacar este código y seguir con el generador predeterminado, pero me gustaría saber la forma correcta de resolverlo.

Una posible solución que he considerado (pero no probado) es el aliasing Word8 usando newtype. Eso causaría muchos cambios en toda la fuente, así que espero que haya una manera más limpia.

EDIT: Como se mencionó en los comentarios a continuación, la respuesta aceptada era muy limpia y fácil de implementar:

newtype EncodedByte = EncodedByte Word8 

instance Arbitrary EncodedByte where 
    arbitrary = liftM EncodedByte $ frequency [(2, elements [ctrlFrameDelim, ctrlEscape, ctrlXon, ctrlXoff]), 
              (8, choose (0, 255))] 

Respuesta

7

Un newtype alias es la solución normas aquí. En la mayoría de los casos, que pueden no incluir el tuyo, esto no es un gran problema porque el contenedor de tipo nuevo solo debe aparecer donde utilizas la clase de tipo Arbitrary. Por ejemplo, es posible que tenga en algún nivel superior:

x <- arbitrary 

Y en vez tendrías

newtype SomeNewType = SNT Word8 
instance Arbitrary SomeNewType where ... 
.... 
    SNT x <- arbitrary 

Lo que probablemente desea no existe como una extensión de GHC - que desea importación y exportación explícita de instancias. Si tenías importaciones instancia explícita esto permitiría:

import Test.QuickCheck hiding (Arbitrary(Word8)) 

Pero romper las porciones de código que actualmente trabaja por las importaciones implícitas de casos:

import Test.QuickCheck (quickCheck) -- note the implicit import of Arbitrary(..) 
+4

Muchas personas parecen considerar esta solución fea. Pero si permite que un "tipo de datos" signifique más que la representación de valores, me parece totalmente razonable. Por ejemplo, no solo está hablando de 'Word8's, sino de' ControlCode's o algo así. – luqui

+0

que funcionó muy bien. Como resultado, el alias no requirió ningún cambio en cascada. Solo necesitaba proporcionar una declaración adicional "instancia Random SomeNewType" para "elegir". –

Cuestiones relacionadas