Can you convert
-- 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)
to pointfree style while maintaining clarity (I know of the program 'pointfree', but would prefer not to obfuscate the code even more)?
Either way, what changes could be made to improve the style of the function, or otherwise makes its intent clearer? The function is intended to be used as below.
$(tupleUnfold 3) ((+ 1), (+ 2), (+ 3)) 2
-- (3, 4, 5)
What are some better naming conventions to use (see the ps, ps', es, and es' variables)?
Here's what I got. Needs Control.Arrow (&&&)
and 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)
Couldn't whittle at it much more without making it totally incomprehensible.
EDIT While not point free, here is the clearest I could make it. Needs 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