Punkt-freie Form im Vergleich zu Stil
-
26-09-2019 - |
Frage
Können Sie konvertieren
-- 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)
zu pointfree Stil, während Klarheit beibehalten (ich kenne das Programm ‚pointfree‘, aber würde es vorziehen, nicht den Code noch mehr zu verschleiern)?
So oder so, welche Änderungen vorgenommen werden könnten, um den Stil der Funktion zu verbessern oder macht sonst seine Absicht klarer? Die Funktion soll wie unten verwendet werden.
$(tupleUnfold 3) ((+ 1), (+ 2), (+ 3)) 2
-- (3, 4, 5)
Was sind einige besser Namenskonventionen zu verwenden (siehe ps, ps', es, und es' Variablen)?
Lösung
Hier ist, was ich bekam. Bedürfnisse Control.Arrow (&&&)
und 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)
kann nicht whittle es viel mehr, ohne dass es völlig unverständlich.
Bearbeiten Während nicht frei zu zeigen, hier ist die klarste ich es machen könnte. Bedürfnisse 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
Andere Tipps
ein wenig unverständlich (versuchen Sie von rechts nach links zu lesen):
tupleUnfold n = do
y <- newName "y"
uncurry lamE . ((:[varP y]) . tupP *** tupE) . unzip .
map (varP &&& (`appE` varE y) . varE) <$> replicateM n (newName "x")
Bearbeiten :
mische von Pfeilen und Funktion Zusammensetzung für die Verarbeitung von
tupleUnfold n = do
y <- newName "y"
uncurry lamE . ((tupP >>> (:[varP y])) *** tupE) . unzip .
map (varP &&& (varE >>> (`appE` varE y))) <$> replicateM n (newName "x")
und mit meist Pfeilen (Leseverarbeitungsfunktion von links nach rechts)
tupleUnfold n = do
y <- newName "y"
(map (varP &&& (varE >>> (`appE` varE y))) >>> unzip >>>
((tupP >>> (:[varP y])) *** tupE) >>> uncurry lamE) <$> replicateM n (newName "x")
Beachten Sie, dass der Pfeil Funktion (>>>) ist äquivalent zu Flip (.)
Ich persönlich denke, es ist ziemlich klar, schon, aber wie wäre es diese:
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
Der Kleisli Zusammensetzung Operator >=>
(von Control.Monad) ist nützlich für die Schaffung von pointfree monadischen Funktionen.