2010-07-25 30 views
7

Dans mon application, j'ai besoin de sérialiser un vecteur contenant un type de données arbitraire, dans ce cas est une liste de doubles. Pour la sérialisation du vecteur, j'importe Data.Vector.Binary.Data.Vector.Binary chevauche une instance binaire [a]

Lors du chargement du module dans GHCi l'erreur suivante se pose:

Overlapping instances for Binary [Double] 
    arising from a use of `decode' at Statistics.hs:57:33-42 
Matching instances: 
    instance (Data.Vector.Generic.Base.Vector v a, Binary a) => 
      Binary (v a) 
    -- Defined in Data.Vector.Binary 
    instance (Binary a) => Binary [a] -- Defined in Data.Binary 

Est-ce la liste une instance de Vector? J'ai regardé la documentation mais je n'ai pas pu trouver une telle instance.

Que puis-je faire pour sérialiser cette structure?

Edit:

J'utilise les versions de package suivantes:

  • vecteur-0.6.0.2
  • instances-0.1.2 vecteur binaire-
  • binaire 0.5.0.2

Voici également un extrait qui montre le problème, cette fois avec une liste de caractères:

import Data.Binary 
import Data.Vector.Binary 
import qualified Data.ByteString.Lazy as L 

main = L.writeFile "/tmp/aaa" $ encode "hello" 
+1

Pourriez-vous s'il vous plaît publier les versions de Binary et Vector que vous utilisez? –

+0

Je suis d'accord que GHCi semble supposer que les listes sont des vecteurs. J'ai regardé le code source pour les instances vectorielles binaires et je ne l'ai pas trouvé. –

+1

Ce n'est pas évident. Edward Kmett a expliqué ce problème il n'y a pas longtemps dans http://stackoverflow.com/questions/3213490/how-do-i-write-if-typeclass-a-then-a-is-also-an-instance-of-b -by-this-definiti –

Répondre

7

Ok, je pense que je vois le problème ici. Le paquet vector-binary-instances définit:

instance (Data.Vector.Generic.Base.Vector v a, Binary a) => Binary (v a) 

ce qui est très mauvais. Cette définition signifie "pour tout type 'v a', ceci est une instance binaire valide". Cela signifie que cette instance est disponible pour tout type correspondant à v a. Cela inclut (mais n'est pas limité à) toutes les listes, tous les foncteurs, et toutes les monades. En guise de démonstration, ghci indique ce qui suit:

Prelude Data.Binary Data.Vector.Binary Data.ByteString.Lazy> :t getChar 
getChar :: IO Char 
Prelude Data.Binary Data.Vector.Binary Data.ByteString.Lazy> encode getChar 
<interactive>:1:0: 
    No instance for (Data.Vector.Generic.Base.Vector IO Char) 
     arising from a use of `encode' at <interactive>:1:0-13 
    Possible fix: 
     add an instance declaration for 
     (Data.Vector.Generic.Base.Vector IO Char) 
    In the expression: encode getChar 
    In the definition of `it': it = encode getChar 

Ici, l'interprète tente d'utiliser cette instance pour getChar :: IO Char, ce qui est évidemment faux.

Réponse courte: n'utilisez pas les instances vectorielles binaires pour le moment. Cette instance est brisée, et étant donné la façon dont les instances se propagent via le code Haskell, cela peut causer des problèmes. Jusqu'à ce que cela soit résolu, vous devriez écrire vos propres instances binaires pour les vecteurs. Vous devriez être en mesure de copier le code des instances de vecteur binaire et la limiter à un type de vecteur monomorphe

instance (Binary a) => Binary (Vector a) where 

Je crois que cela va fonctionner avec un vecteur qui est une instance de Data.Vector.Generic.Vector.

Vous pouvez également contacter le mainteneur d'instances binaires-vectorielles à ce sujet.

+0

Merci beaucoup pour l'explication, aussi le lien vers la réponse d'Edward Kmett a aidé à comprendre pourquoi cela arrive. Le citant: «À bien des égards, la syntaxe des définitions 'instance' et 'class' est à rebours. '.Je vais suivre vos suggestions, pour lesquelles je suis reconnaissant. – uu1101

+0

De rien; Je suis content que cela ait été utile. –

+0

Le paquet a été mis à jour. Je viens d'énumérer séparément les cas vectoriels en boîte et non boxés (notez que vous ne pouvez pas simplement utiliser 'Vector a', car ce sont seulement les cas en boîte). –