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)?
Tacit programming, also called point-free style, is a programming paradigm in which function definitions do not identify the arguments (or "points") on which they operate. Instead the definitions merely compose other functions, among which are combinators that manipulate the arguments.
What is Point Free. Point free style is basically you write code but don't explicitly provide the arguments in the code. This is usefully especially in callbacks where a function is expected. I'll show you the examples in TypeScript, it'll work the same in JavaScript/ES6.
Point free style means that the code doesn't explicitly mention it's arguments, even though they exist and are being used. This works in Haskell because of the way functions work.
Point-free style means programming where you don't have to name arguments or intermediate values. The main reason we do it is to be able to code at the right level of abstraction. You don't want to be thinking about, "How do I name this function?" or "How do I name this argument?" Stuff like that.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With