J'ai un tas de fonctions comme :
f1 :: String -> String -> ... -> String -> ()
f1 a b ... z = g [("a", a), ("b", b), ... ("z", z)]
...
fn :: String -> Int -> String -> ... -> String -> ()
fn a b ... z = g [("a", a), ("b", show b), ... ("z", z)]
Donc l'utilisateur peut juste les appeler comme f1 "abc" "def"
. Je ne veux pas qu'il fasse cela parce qu'il peut facilement intervertir "abc" et "def" par erreur (et Dieu sait combien de temps il perdrait en déboguant). Je veux qu'il passe des arguments comme fk (A "abc") (B "def")
D'après ce que je vois, il y a 2 options :
-
Massive
data
construction et fonction de déballage massif :data Value = A String | B String | C Int | D String ... unpack :: Value -> String unpack (A a) = a unpack (B b) = b unpack (C c) = show c unpack (D c) = d
Beaucoup de code.
-
Classe de type commune et nouveaux types :
EDIT : Ok alors, nous pouvons utiliserGeneralizedNewtypeDeriving
dans un cas aussi simple.{-# LANGUAGE GeneralizedNewtypeDeriving #-} class Value a where unpack :: a -> String instance Value String where unpack = id instance Value Int where unpack = show newtype A = A String deriving Value newtype B = B String deriving Value newtype C = C Int deriving Value newtype D = D String deriving Value ...
C'est beaucoup mieux, mais tout
fk
ressemblerait àfk a b ... z = g [("a", unpack a), ("b", unpack b), ... ("z", unpack z)]
Beaucoup de code et de duplication.
Ce que je veux c'est un tour de magie qui me permettrait :
fk a b ... z = g [("a", a), ("b", b), ... ("z", z)]
g = h . map (second unpack)