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)?

Était-ce utile?

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).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top