Domanda

Si può convertire

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

per stile pointfree, pur mantenendo la chiarezza (non conosco il programma 'pointfree', ma preferirebbe non offuscare il codice anche di più)?

In entrambi i casi, quali cambiamenti potrebbe essere fatto per migliorare lo stile della funzione, o fa comunque il suo intento più chiaro? La funzione è destinato ad essere utilizzato come sotto.

$(tupleUnfold 3) ((+ 1), (+ 2), (+ 3)) 2
-- (3, 4, 5)

Quali sono alcune convenzioni meglio di denominazione da utilizzare (vedi ps, ps', es, e es' variabili)?

È stato utile?

Soluzione

Ecco quello che ho ottenuto. Bisogni Control.Arrow (&&&) e 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)

Impossibile Whittle a molto di più senza che lo rende del tutto incomprensibile.

Modifica Anche se non Point gratuito, qui è la più chiara ho potuto farlo. Bisogni 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

Altri suggerimenti

un po 'più incomprensibile (provate a leggere da destra a sinistra):

tupleUnfold n = do
  y <- newName "y"
  uncurry lamE . ((:[varP y]) . tupP *** tupE) . unzip .   
   map (varP &&& (`appE` varE y) . varE) <$> replicateM n (newName "x")

Modifica :
miscela di frecce e composizione di funzioni di elaborazione

tupleUnfold n = do
  y <- newName "y"
  uncurry lamE . ((tupP >>> (:[varP y])) *** tupE) . unzip .
    map (varP &&& (varE >>> (`appE` varE y))) <$> replicateM n (newName "x")

e utilizzando prevalentemente frecce (lettura funzione elaborazione da sinistra a destra)

tupleUnfold n = do
  y <- newName "y"
  (map (varP &&& (varE >>> (`appE` varE y))) >>> unzip >>>
    ((tupP >>> (:[varP y])) *** tupE) >>> uncurry lamE) <$> replicateM n (newName "x")

nota che la funzione freccia (>>>) è equivalente a vibrazione (.)

Personalmente penso che sia abbastanza chiaro già, ma come su questo:

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

Il >=> Kleisli operatore di composizione (da Control.Monad) è utile per creare pointfree funzioni monadici.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top