forme sans point par rapport à un style
-
26-09-2019 - |
Question
Pouvez-vous convertir
-- tupleUnfold :: forall a. ((forall b. a -> b)) -> a -> ((b))
tupleUnfold :: Int -> ExpQ
tupleUnfold n = do
xs <- forM [1 .. n] (const . newName $ "x")
y <- newName "y"
let y' = varE y
g (ps', es') x = (varP x : ps', appE (varE x) y' : es')
(ps, es) = foldl' g ([], []) xs
lamE [tupP ps, varP y] (tupE es)
au style Pointfree tout en maintenant la clarté (je sais du programme « Pointfree », mais préférerait ne pas obscurcir le code encore plus)?
De toute façon, quels changements pourraient être apportés pour améliorer le style de la fonction, ou fait par ailleurs son intention plus claire? Cette fonction est destinée à être utilisée comme ci-dessous.
$(tupleUnfold 3) ((+ 1), (+ 2), (+ 3)) 2
-- (3, 4, 5)
Quelles sont les conventions de nommage mieux à l'utilisation (voir le ps, ps, es, et es de variables)?
La solution
Voici ce que je suis. Besoins Control.Arrow (&&&)
et Control.Applicative (<$>)
.
tupleUnfold :: Int -> ExpQ
tupleUnfold n = do
y <- newName "y"
(ps,es) <- unzip . map (varP &&& (`appE` varE y) . varE)
<$> replicateM n (newName "x")
lamE [tupP ps, varP y] (tupE es)
Impossible Whittle à beaucoup plus sans la rendre totalement incompréhensible.
EDIT Sans point libre, voici le le plus clair je pourrais le faire. Besoins Data.Function (on)
tupleUnfold :: Int -> ExpQ
tupleUnfold n = do
y <- newName "y"
xs <- replicateM n (newName "x")
let exps = tupE $ zipWith appVars xs (repeat y)
pats = tupP $ map varP xs
lamE [pats, varP y] exps
where
appVars = appE `on` varE
Autres conseils
un peu plus incompréhensible (essayez de lire de droite à gauche):
tupleUnfold n = do
y <- newName "y"
uncurry lamE . ((:[varP y]) . tupP *** tupE) . unzip .
map (varP &&& (`appE` varE y) . varE) <$> replicateM n (newName "x")
EDIT :
mélanger de flèches et de composition de fonction pour le traitement
tupleUnfold n = do
y <- newName "y"
uncurry lamE . ((tupP >>> (:[varP y])) *** tupE) . unzip .
map (varP &&& (varE >>> (`appE` varE y))) <$> replicateM n (newName "x")
et la plupart du temps à l'aide des flèches (lecture fonction de traitement de gauche à droite)
tupleUnfold n = do
y <- newName "y"
(map (varP &&& (varE >>> (`appE` varE y))) >>> unzip >>>
((tupP >>> (:[varP y])) *** tupE) >>> uncurry lamE) <$> replicateM n (newName "x")
Notez que la fonction de flèche (>>>) est équivalent à bascule (.)
Personnellement, je pense qu'il est déjà assez clair, mais que diriez-vous ceci:
tupleUnfold :: Int -> ExpQ
tupleUnfold = mapM (const . newName $ "x") . enumFromTo 1 >=> \xs -> do
y <- newName "y"
let y' = varE y
g (ps', es') x = (varP x : ps', appE (varE x) y' : es')
f ps = lamE [tupP ps, varP y] . tupE
uncurry f $ foldl' g ([],[]) xs
est utile pour la création de fonctions Pointfree monadique opérateur de composition Kleisli >=>
(de Control.Monad).