2010-03-19 3 views
1

je trouve qu'il est extrêmement difficile de décrire mon problème, donc ici va rien:variables de type de liaison qui ne se produisent que dans les assertions

J'ai un tas d'affirmations sur le type de fonction. Ces assertions reposent sur une variable de type qui n'est utilisée pour aucun paramètre de la fonction, mais qui n'est utilisée que pour les liaisons internes. Chaque fois que j'utilise cette fonction, elle ne compile pas parce que, bien sûr, le compilateur n'a aucune information à partir de laquelle deviner de quel type lier ma variable de type. Voici le code:

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, 
    UndecidableInstances, FlexibleContexts, EmptyDataDecls, ScopedTypeVariables, 
    TypeOperators, TypeSynonymInstances #-} 

class C a a' where convert :: a -> a' 
class F a b where apply :: a -> b 
class S s a where select :: s -> a 

data CInt = CInt Int 

instance S (Int,String) Int where select (i,_) = i 
instance F Int CInt where apply = CInt 

f :: forall s a b . (S s a, F a b) => s -> b 
f s = 
    let v = select s :: a 
     y = apply v :: b 
    in y 

x :: Int 
x = f (10,"Pippo") 

Et voici l'erreur générée:

FunctorsProblems.hs:21:4: 
    No instances for (F a Int, S (t, [Char]) a) 
     arising from a use of `f' at FunctorsProblems.hs:21:4-17 
    Possible fix: 
     add an instance declaration for (F a Int, S (t, [Char]) a) 
    In the expression: f (10, "Pippo") 
    In the definition of `x': x = f (10, "Pippo") 
Failed, modules loaded: none. 
Prelude> 
+1

Oui, ce que vous dites est correct. Quelle est la question? Cherchez-vous une explication de l'erreur, ou des solutions de contournement possibles? –

+0

Je souhaite comprendre comment je peux aider le compilateur à comprendre les types intermédiaires du calcul, mais je ne sais pas comment ... Alors oui, ce sont des solutions de contournement que je cherche! –

Répondre

1

Vous essayez de recouper certains ensemble d'instances de classes et compilateur il n'y a aucun moyen de dire que cette intersection sera être vide ou entrée unique.
Vous souhaitez forcer le compilateur à choisir le bon type pour vous sans savoir quels problèmes (perte d'informations ou complexité des calculs) cette décision peut entraîner dans votre programme. Si vous voulez faire cela, vous devriez donner un indice au compilateur quel est le meilleur type "a" pour une paire spécifique "s" et "b" (avec nous de FunctionalDependencies que vous avez spécifié).

class E x a | x -> a 
instance (S s Int, F Int CInt) => E (s, CInt) Int 
f :: forall s a b . (E (s,b) a) => s -> b 

probablement il y a la façon de spécifier l'ordre des types préférés de « a » pour deux « s » et « b » avec plus déduisent des meilleures « a » (utilisation de type niveau ou quelque chose comme que pour attacher cette information).

Questions connexes