2012-05-10 44 views
6

Pakiet konstruktywne-Algebra umożliwia określenie przykłady algebraicznych moduły (np vectorial przestrzenie że stosuje się pierścień gdzie wymagana jest pole)Określenie modułu matematycznego stosując pakiet konstruktywne-matematycznego

to moja próba na zdefiniowanie moduł:

{-# 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] 

To nie przez:

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. 

Jeśli komentarz instancję Group się, a następnie:

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. 

czytałem to jako wymagające wystąpienie Ring A mieć Module Integer A który nie ma sensu i jest nie jest wymagane w definicji klasy:

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

Czy możesz to wyjaśnić?

+1

Czy martwisz się, że twoja instancja 'Group' dla' A' w rzeczywistości nie definiuje grupy? Na przykład 'let a = [(1," foo ")]', następnie 'a <+> neg a = [(1," foo "), (- 1," foo ")]", który nie jest taki sam jak "zero". –

+0

Tak, wiem. Pierwotnym pomysłem było zredukowanie 'a ++ b' poprzez grupowanie na identycznych łańcuchach. Pominąłem redukcję do normalnej formy, aby uprościć przykład. – user21338

Odpowiedz

5

Pakiet zawiera

instance Ring a => Group a where ... 

instancja głowicę a wyniki ekspresji każdego rodzaju, aby każdy przypadek z dowolnego innego typu ekspresji pokrywają. To nakładanie się powoduje tylko błąd, jeśli taka instancja jest faktycznie używana gdzieś. W module, należy użyć instancji w

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

Klasa Module posiada AbelianGroup presję na m parameter¹. Oznacza to ograniczenie z Group. W tym przypadku instancja Group z A musi zostać sprawdzona. Kompilator znajduje dwie pasujące instancje.

To jest pierwszy zgłoszony błąd.

Następna, ponieważ kompilator próbuje znaleźć instancję AbelianGroup dla A. Jedyną instancją kompilator wie o tym momencie jest

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

więc próbuje znaleźć instance Ring A where ..., ale oczywiście nie jest jeden.

Zamiast zakomentowałeś instance Group A where ..., należy dodaj

instance AbelianGroup a 

(nawet jeśli jest to kłamstwo, po prostu chcemy, aby go skompilować w tej chwili), a także dodać OverlappingInstances do
{-# LANGUAGE #-} Pragma .

Po wybraniu OverlappingInstances wybierana jest najbardziej dopasowana instancja, więc robi to, co chcesz.

¹ Przy okazji, numer A nie jest instancją AbelianGroup i zgodnie z prawem nie może być, jeśli zamówienie nie ma znaczenia na liście [(Integer,String)].

+0

Teraz moja pragma zawiera również "OverlappingInstances". Dodałem instancję "AbelianGroup A" do ciała, ale nadal mam "nakładające się instancje dla grupy A" i "nakładające się instancje dla AbelianGroup A' – user21338

+0

Którą wersję GHC? Analogiczny przypadek kompiluje się tutaj z ghc> = 7.2. W przypadku ghc <= 7.0 moduł definiujący 'Group' i' AbelianGroup' również potrzebuje OverlappingInstances - ale to oznaczałoby modyfikację pakietu. –

+0

To jest ghc 7.0.4 i tak: Dodałem 'OverlappingInstances' do' Group.hs', a teraz kompiluje się zgodnie z przeznaczeniem. Wielkie dzięki! – user21338

2

Ten typ sprawdza się bez nieprzyjemnych rozszerzeń językowych.

{-# 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] 

jest trochę mylący, że <+><*> i neg są określone niezależnie w Ring i Group; są one całkowicie oddzielnymi symbolami, ale potem są łączone w ogólnej instancji, która tworzy wszystkie RingsGroups, więc jeśli zdefiniowano, to nie można zdefiniować Group, ponieważ jest już mowa. Nie jestem pewien, czy jest to wymuszone na autorze, tak jak działa system klasy typów. Module wymaga Ring lub raczej CommutativeRing. CommutativeRing po prostu zmienia nazwę na Ring; nic więcej nie zostanie określone. Ma was zobowiązać do tego, co w Haskell stanowi niewzruszone twierdzenie o przemienności. Więc masz "udowodnić prawa CommutativeRing", że tak powiem, poza modułem przed wykonaniem instancji Module. Zauważ jednak, że te prawa są wyrażone w propozycjach quickcheck, więc powinieneś uruchomić szybkie sprawdzanie na propMulComm i i propCommutativeRing specjalizowane dla tego typu.

Nie wiem, co robić o jeden i zero, ale można ominąć punkt o kolejności stosując odpowiednią strukturę, może:

import qualified Data.Set as S 

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

ale o newtyped można też np przedefiniować Eq na A's, aby to zrozumieć, jak przypuszczam. W rzeczywistości musisz uruchomić propozycje szybkiego sprawdzania.


Edit: Tutaj jest wersja z dodatkiem materiału potrzebnego do QuickCheck http://hpaste.org/68351 wraz z „Nie” i „OK” QuickCheck-deklaracje dla różnych instancji EQ. Ten pakiet wydaje mi się całkiem rozsądny; Myślę, że powinieneś przedefiniować moduł, jeśli nie chcesz biznesu Ring and CommutativeRing, ponieważ mówi on: "Zastanów się tylko nad przemiennym przypadkiem, zamiast tego można zaimplementować lewy i prawy moduł". W przeciwnym razie nie będziesz w stanie użyć quickcheck, co jest oczywiście głównym punktem pakietu, teraz, kiedy widzę, co jest grane, i które zrobił niesamowicie łatwo zrobić. Tak jak to jest A, jest to dokładnie to, co próbuje wykluczyć z wszechprzenikającego użycia kontroli błyskawicznej, co z pewnością byłoby bardzo trudne do oszukania w tego rodzaju przypadkach.

+0

Wolę pozostawić '(<*>)' i 'one' jako' undefined', ponieważ nie zamierzam, aby 'A' miał strukturę pierścienia iw ten sposób dostanę błąd za każdym razem, gdy spróbuję go użyć. – user21338

Powiązane problemy