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

War es hilfreich?

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top