Dites que j'ai un tuple comme ('a',(1,("Hello",False))
. Juste pour le plaisir (lire: apprentissage), je voudrais créer une fonction qui applique une fonction de la forme correcte à un tel tuple et renvoie le résultat. Exemple d'utilisation:Haskell: Fonction pour appliquer une fonction aux 2-tuples imbriqués
applyFnToTuple ('o',('t','w')) $ \a b c -> [a,b,c] == "otw"
applyFnToTuple ('h','i') $ \a b -> [a,b] == "hi"
applyFnToTuple ("hello",('y','o')) $ \a b c -> a ++ [b,c]
je l'ai fait la plus grande partie comme suit:
type family TupleFn ty out where
TupleFn (a,b) output = a -> (TupleFn b output)
TupleFn b output = b -> output
class ApplyFnToTuple a where
applyFnToTuple :: a -> TupleFn a out -> out
instance ApplyFnToTuple b => ApplyFnToTuple (a,b) where
applyFnToTuple (a,b) fn = applyFnToTuple b (fn a)
instance ApplyFnToTuple a where
applyFnToTuple b fn = fn b
Le point d'achoppement est que dernière instance. Je m'attends entièrement à devoir ajouter {-# OVERLAPPABLE #-}
puisque a
est plus général que le (a,b)
. Je ai aussi du mal à voir exactement comment GHC pourrait résoudre a
et la version correcte de ma classe TupleFn
et connaître le bon type sig, mais je peux facilement mettre cela à mon propre manque de compréhension. Mais en tout cas, l'erreur réelle GHCi me donne est:
Couldn't match expected type ‘a -> out’
with actual type ‘TupleFn a out’
Relevant bindings include
fn :: TupleFn a out (bound at examples.hs:574:22)
b :: a (bound at examples.hs:574:20)
applyFnToTuple :: a -> TupleFn a out -> out
(bound at examples.hs:574:5)
The function ‘fn’ is applied to one argument,
but its type ‘TupleFn a out’ has none
In the expression: fn b
In an equation for ‘applyFnToTuple’: applyFnToTuple b fn = fn b
Failed, modules loaded: none.
Pour autant que je sache, aucune version de mon TupleFn retourne quelque chose sans argument, donc je ne comprends pas vraiment l'erreur. Cependant, je trouve qu'il peut être fait de compiler simplement en changeant la dernière instance à quelque chose par exemple plus concret:
instance ApplyFnToTuple Char where
applyFnToTuple b fn = fn b
Mais cela signifie que je dois définir beaucoup de cas similaires, etc ce qui est indésirable.
Ce que je voudrais savoir, est-ce qu'il ya un moyen relativement facile de faire fonctionner la version plus générale, et pourquoi cette erreur particulière?
:) Merci
PS: Je suis en GHC 7.10.1
En relation: [Comment créer la fonction la plus générique possible qui applique une fonction aux éléments de tuple] (http://stackoverflow.com/questions/31220903/haskell-how-to-create-most-generic-function-possible- that-applique-a-function-to) – Cirdec
Voilà une autre de mes questions. Cela implique un tuple mais n'est pas vraiment lié ☺ – jsdw
Proposition: au lieu de '(a, (b, c))', utilisez '(a, (b, (c,())))'. Ensuite, il est facile d'écrire l'instance 'ApplyFnToTuple()' qui ne prend aucun argument et renvoie la sortie, et il n'y a aucun risque de chevauchement. –