2012-05-10 9 views
6

El paquete constructivo-álgebra le permite definir los casos de algebraica módulos (como espacios vectoriales pero utilizando un anillo donde se requiere un campo)Definición de un módulo de álgebra usando el paquete constructivo-álgebra

Este es mi intento de definir un módulo :

{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances #-} 
module A where 
import Algebra.Structures.Module 
import Algebra.Structures.CommutativeRing 
import Algebra.Structures.Group 

newtype A = A [(Integer,String)] 

instance Group A where 
    (A a) <+> (A b) = A $ a ++ b 
    zero = A [] 
    neg (A a) = A $ [((-k),c) | (k,c) <- a] 


instance Module Integer A where 
    r *> (A as) = A [(r <*> k,c) | (k,c) <- as] 

fracasa por:

A.hs:15:10: 
    Overlapping instances for Group A 
     arising from the superclasses of an instance declaration 
    Matching instances: 
     instance Ring a => Group a -- Defined in Algebra.Structures.Group 
     instance Group A -- Defined at A.hs:9:10-16 
    In the instance declaration for `Module Integer A' 

A.hs:15:10: 
    No instance for (Ring A) 
     arising from the superclasses of an instance declaration 
    Possible fix: add an instance declaration for (Ring A) 
    In the instance declaration for `Module Integer A' 
Failed, modules loaded: none. 

Si comento la instancia Group a cabo, a continuación:

A.hs:16:10: 
    No instance for (Ring A) 
     arising from the superclasses of an instance declaration 
    Possible fix: add an instance declaration for (Ring A) 
    In the instance declaration for `Module Integer A' 
Failed, modules loaded: none. 

leí esto como que requiere una instancia de Ring A tener Module Integer A lo cual no tiene sentido y es no requerido en la definición de la clase:

class (CommutativeRing r, AbelianGroup m) => Module r m where 
    -- | Scalar multiplication. 
    (*>) :: r -> m -> m 

¿Podría explicar esto?

+1

¿Le preocupa que su instancia 'Group' para' A' no defina realmente un grupo? Por ejemplo, 'let a = [(1," foo ")]', then 'a <+> neg a = [(1," foo "), (- 1," foo ")]' que no es lo mismo que 'cero'. –

+0

Sí, lo sé. La idea original era reducir 'a ++ b' agrupando cadenas idénticas. Me salté la reducción a la forma normal para simplificar el ejemplo. – user21338

Respuesta

5

El paquete contiene un

instance Ring a => Group a where ... 

La cabeza instancia a partidos cada tipo de expresión, por lo que cualquier instancia con cualquier otro tipo de expresión se solaparán. Esa superposición solo causa un error si tal instancia realmente se usa en alguna parte. En su módulo, utiliza la instancia en

instance Module Integer A where 
    r *> (A as) = A [(r <*> k,c) | (k,c) <- as] 

Module La clase tiene una restricción en la AbelianGroupm parameter¹. Eso implica una restricción Group. Por lo tanto, para esta instancia, se debe buscar la instancia Group de A. El compilador encuentra dos instancias coincidentes.

Ese es el primer error informado.

El siguiente es porque el compilador intenta encontrar una instancia AbelianGroup para A. El único caso en que el compilador sabe en ese punto es

instance (Group a, Ring a) => AbelianGroup a 

por lo que trata de encontrar la instance Ring A where ..., pero por supuesto no hay uno.

En lugar de comentario la instance Group A where ..., se debe añadir un

instance AbelianGroup a 

(incluso si es una mentira, sólo queremos que se compile en el momento) y también añadir OverlappingInstances a la pragma
{-# LANGUAGE #-} .

Con OverlappingInstances, se elige la instancia de coincidencia más específica, por lo que hace lo que quiere aquí.

¹ Por cierto, su A no es una instancia de AbelianGroup y legítimamente no puede ser a menos que el orden sea irrelevante en la lista [(Integer,String)].

+0

Ahora mi pragma contiene 'OverlappingInstances' también. Agregué 'instance AbelianGroup A' al cuerpo pero aún así' instancias superpuestas para el grupo A 'y 'instancias superpuestas para AbelianGroup A' – user21338

+0

¿Qué versión de ghc? Un caso análogo se compila aquí con ghc> = 7.2. Para ghc <= 7.0, el módulo que define 'Group' y' AbelianGroup' también necesita OverlappingInstances, pero eso significaría modificar el paquete. –

+0

Es ghc 7.0.4 y sí: agregué 'OverlappingInstances' a' Group.hs' y ahora se compila según lo previsto. ¡Muchas gracias! – user21338

2

Este tipo comprueba sin extensiones de lenguaje desagradables.

{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances #-} 
module A where 
import Algebra.Structures.Module 
import Algebra.Structures.CommutativeRing 
import Algebra.Structures.Group 

newtype A = A [(Integer,String)] 

instance Ring A where 
    A xs <+> A ys = A (xs ++ ys) 
    neg (A a) = A $ [((-k),c) | (k,c) <- a] 
    A x <*> A y = A [b | a <- x, b <- y ] 
    one = A [] 
    zero = A [] 

instance Module Integer A where 
    r *> (A as) = A [(r <*> k,c) | (k,c) <- as] 

Es un poco confuso que <+><*> y neg se definen independientemente en Ring y Group; son símbolos completamente separados, pero luego se juntan en la instancia general que hace que todos RingsGroups, por lo que si se define Ring, no se debe definir Group, ya que ya se ha hablado. No estoy seguro de que esto sea forzado al autor por la forma en que funciona el sistema de clases de tipo. Module requiere Ring o más bien CommutativeRing. CommutativeRing simplemente está renombrando Ring; nada más debe ser definido. Se supone que debe comprometerte a lo que está en Haskell una afirmación incontrolable de conmutatividad. Por lo tanto, se supone que debe "probar las leyes CommutativeRing", por así decirlo, fuera del módulo antes de realizar la instancia Module. Sin embargo, tenga en cuenta que estas leyes se expresan en proposiciones de comprobación rápida, por lo que se supone que debe ejecutar la comprobación rápida en propMulComm y propCommutativeRing especializada en este tipo.

No sabe qué hacer con uno y cero, pero se puede llegar más allá del punto sobre el orden mediante el uso de una estructura adecuada, tal vez:

import qualified Data.Set as S 

newtype B = B {getBs :: S.Set (Integer,String) } 

Pero habiendo newtyped puede también, por ejemplo, redefinir Eq en A para darle sentido, supongo. De hecho, debe ejecutar las proposiciones de comprobación rápida.


Editar: Aquí hay una versión con material añadido necesario para QuickCheck http://hpaste.org/68351 junto con "Error" y QuickCheck-declaraciones "OK" para diferentes casos Eq. Este paquete me parece bastante razonable; Creo que debería redefinir el Módulo si no desea el negocio Ring y CommutativeRing, ya que él dice que "considere [s] solo el caso conmutativo, en su lugar sería posible implementar módulos izquierdo y derecho". De lo contrario, no podrá usar Quickcheck, que es claramente el punto principal del paquete, ahora que veo lo que sucede y lo ha hecho increíblemente fácil de hacer. Como es A, es exactamente el tipo de cosa que está tratando de descartar con el uso omnipresente de Quickcheck, que seguramente sería muy difícil de engañar en este tipo de casos.

+0

Prefiero dejar '(<*>)' y 'one' como' undefined' porque no pretendo que 'A' tenga una estructura de anillo y así obtendré un error siempre que intente usarlo. – user21338

Cuestiones relacionadas