Pregunta

¿Se puede 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)

para pointfree estilo, manteniendo la claridad (sé de la 'pointfree' programa, pero preferiría no ofuscar el código aún más)?

De cualquier manera, ¿qué cambios se podrían hacer para mejorar el estilo de la función, o de otra manera hace su clara intención? La función está destinado a ser utilizado como a continuación.

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

¿Cuáles son algunas de las convenciones de nombres para un mejor uso (ver el PS, PS', ES, y es' variables)?

¿Fue útil?

Solución

Esto es lo que tengo. Control.Arrow (&&&) necesidades y 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)

No se pudo sacar ventaja en ello mucho más sin que sea totalmente incomprensible.

Editar Si bien no es punto libre, aquí está el más clara que podría hacerlo. Necesidades 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

Otros consejos

un poco más incomprensible (tratar de leer de derecha a izquierda):

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

Editar :
Mezcla de flechas y la composición de funciones para procesar

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

y utilizando la mayoría de las flechas (leer función de procesamiento de izquierda a derecha)

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

nota que la función de flecha (>>>) es equivalente a flip (.)

En lo personal creo que está bastante claro ya, pero ¿qué tal esto:

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

El >=> Kleisli operador composición (de Control.Monad) es útil para crear pointfree funciones monádicos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top