Wie heißt das funktionale Argument in Fold


10

In der Funktion höherer Ordnung falten / reduzieren Sie den Namen des Funktionsarguments, falls vorhanden?

Ich arbeite an einer monadischen tabellarischen Verarbeitungsbibliothek, in der Zeilen gefaltet werden, um einfache Analysen zu erstellen (z. B. das Ermitteln des Minimums, Maximums und Durchschnitts einer Spalte). Ich suche daher nach einem soliden Namen für das Argument der foldFunktion, und jeder Name, der in der ML-Community gut etabliert ist (oder Haskell oder Common Lisp als zweiter und dritter Kandidat), wäre interessant.

Ein Name wie fist in der Beschreibung von foldFunktionen üblich, jedoch nicht beschreibend und ein Substantiv wäre besser geeignet.


10
Es gibt keinen. Tatsächlich gibt es nicht einmal einen allgemein verwendeten Namen für Katamorphismen (Falte)
Daniel Gratzer

2
Wenn dies eine Frage für eine Schulaufgabe oder Prüfung ist, müssen Sie die Antwort vom Lehrer oder Lehrbuch erhalten, nicht von uns. Er könnte es etwas anderes nennen. Was in einem Klassenzimmer gelehrt wird, ist nicht immer das, was in der realen Welt üblicherweise verwendet wird.
Robert Harvey

7
@ RobertHarvey Dies ist keine Prüfungsfrage (?) Oder ähnliches. Als Programmierer denke ich, dass die Auswahl guter Namen für die Programmierung von Objekten (Typen, Variablen usw.) sehr wichtig ist. Und wenn etwas einen bekannten Namen hat, dann gibt es keinen Grund, ihn nicht zu verwenden - abgesehen von Unwissenheit, und dafür sind Fragen gedacht.
user40989

9
@ Izkata Nein, das ist falsch. Eine Funktion höherer Ordnung ist eine Funktion, die eine Funktion übernimmt. foldist eine Funktion höherer Ordnung. Das Argument zu folden ist nur das, ein Argument
Daniel Gratzer

1
@jozefg Das als Antwort auf den zweiten Teil Ihres Kommentars. Zum ersten Teil (und zur Frage) siehe meinen Beitrag zu Meta. Sie werden prozedurale Parameter genannt.
Izkata

Antworten:


8

Ich weiß nicht, ob es eine einzige Antwort darauf gibt, wie @jozefg erwähnte. Und so rein aus Spekulation, hier ist eine mögliche Erklärung:

Ich vermute, der Grund dafür ist, dass der Typ - zum Beispiel (a -> b -> b)bei Haskellfoldr - aussagekräftiger ist als jeder Name, den man sich vorstellen könnte. Da die Parameter aund btype alles sein können , kann die Funktion auch so ziemlich alles tun. So können Sie mit Namen sind links wie function, combiner, morphism, und argument, die nicht besonders sinnvoll entweder. Könnte auch einen kurzen, nicht ablenkenden Namen verwenden.

Ein weiteres Beispiel ist die id :: a -> aFunktion: Wie sollten Sie ihr Argument nennen? Auch hier denke ich, dass idder Typ aussagekräftiger ist als sein Argumentname.

Ich stimme Ihnen jedoch zu - es scheint, dass es einen gemeinsamen Namen geben sollte, vielleicht in der Mathematik. Ich hoffe, jemand kann mich diesbezüglich korrigieren.


Einige Beispiele für seinen Namen in echtem Code:

In Haskells Bibliotheken heißt es meistens f(und manchmal operatorin den Kommentaren):

class Foldable t where
    -- | Map each element of the structure to a monoid,
    -- and combine the results.
    foldMap :: Monoid m => (a -> m) -> t a -> m
    foldMap f = foldr (mappend . f) mempty

    -- | Right-associative fold of a structure.
    --
    -- @'foldr' f z = 'Prelude.foldr' f z . 'toList'@
    foldr :: (a -> b -> b) -> b -> t a -> b
    foldr f z t = appEndo (foldMap (Endo . f) t) z

    -- | Right-associative fold of a structure, 
    -- but with strict application of the operator.
    foldr' :: (a -> b -> b) -> b -> t a -> b
    foldr' f z0 xs = foldl f' id xs z0
      where f' k x z = k $! f x z

    -- | Left-associative fold of a structure.
    --
    -- @'foldl' f z = 'Prelude.foldl' f z . 'toList'@
    foldl :: (a -> b -> a) -> a -> t b -> a
    foldl f z t = appEndo (getDual (foldMap (Dual . Endo . flip f) t)) z

    -- | Left-associative fold of a structure.
    -- but with strict application of the operator.
    --
    -- @'foldl' f z = 'List.foldl'' f z . 'toList'@
    foldl' :: (a -> b -> a) -> a -> t b -> a
    foldl' f z0 xs = foldr f' id xs z0
      where f' x k z = k $! f z x

    -- | A variant of 'foldr' that has no base case,
    -- and thus may only be applied to non-empty structures.
    --
    -- @'foldr1' f = 'Prelude.foldr1' f . 'toList'@
    foldr1 :: (a -> a -> a) -> t a -> a
    foldr1 f xs = fromMaybe (error "foldr1: empty structure")
                    (foldr mf Nothing xs)
      where
        mf x Nothing = Just x
        mf x (Just y) = Just (f x y)

    -- | A variant of 'foldl' that has no base case,
    -- and thus may only be applied to non-empty structures.
    --
    -- @'foldl1' f = 'Prelude.foldl1' f . 'toList'@
    foldl1 :: (a -> a -> a) -> t a -> a
    foldl1 f xs = fromMaybe (error "foldl1: empty structure")
                    (foldl mf Nothing xs)
      where
        mf Nothing y = Just y
        mf (Just x) y = Just (f x y)

-- instances for Prelude types

instance Foldable Maybe where
    foldr _ z Nothing = z
    foldr f z (Just x) = f x z

    foldl _ z Nothing = z
    foldl f z (Just x) = f z x

instance Ix i => Foldable (Array i) where
    foldr f z = Prelude.foldr f z . elems
    foldl f z = Prelude.foldl f z . elems
    foldr1 f = Prelude.foldr1 f . elems
    foldl1 f = Prelude.foldl1 f . elems

-- | Monadic fold over the elements of a structure,
-- associating to the right, i.e. from right to left.
foldrM :: (Foldable t, Monad m) => (a -> b -> m b) -> b -> t a -> m b
foldrM f z0 xs = foldl f' return xs z0
  where f' k x z = f x z >>= k

-- | Monadic fold over the elements of a structure,
-- associating to the left, i.e. from left to right.
foldlM :: (Foldable t, Monad m) => (a -> b -> m a) -> a -> t b -> m a
foldlM f z0 xs = foldr f' return xs z0
  where f' x k z = f z x >>= k

-- | Map each element of a structure to an action, evaluate
-- these actions from left to right, and ignore the results.
traverse_ :: (Foldable t, Applicative f) => (a -> f b) -> t a -> f ()
traverse_ f = foldr ((*>) . f) (pure ())

-- | Map each element of a structure to a monadic action, evaluate
-- these actions from left to right, and ignore the results.
mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()
mapM_ f = foldr ((>>) . f) (return ())

Es heißt auch f in Clojure :

(def
    ^{:arglists '([f coll] [f val coll])
      :doc "f should be a function of 2 arguments. If val is not supplied,
  returns the result of applying f to the first 2 items in coll, then
  applying f to that result and the 3rd item, etc. If coll contains no
  items, f must accept no arguments as well, and reduce returns the
  result of calling f with no arguments.  If coll has only 1 item, it
  is returned and f is not called.  If val is supplied, returns the
  result of applying f to val and the first item in coll, then
  applying f to that result and the 2nd item, etc. If coll contains no
  items, returns val and f is not called."
      :added "1.0"}    
    reduce
     (fn r
       ([f coll]
             (let [s (seq coll)]
               (if s
                 (r f (first s) (next s))
                 (f))))
       ([f val coll]
          (let [s (seq coll)]
            (if s
              (if (chunked-seq? s)
                (recur f 
                       (.reduce (chunk-first s) f val)
                       (chunk-next s))
                (recur f (f val (first s)) (next s)))
              val)))))

6

Ich bin nicht einverstanden mit der Idee, dass fdas Funktionsargument von ein schlechter Name ist fold. Der Grund, warum wir beschreibende Namen in der Programmierung wünschen, ist, dass wir wissen, was der Name beschreibt, und der Name fwird üblicherweise in der Mathematik (und in funktionalen Programmiersprachen) für eine Funktion (wie gund h) verwendet.

Wir wissen fast nichts darüber f(von Natur aus, da wir, wenn wir genauer darauf eingehen könnten, nicht foldso viele Dinge verwenden könnten ), und der Name fsagt uns alles, was wir wissen müssen, außer dass es eine Funktion von zwei Argumenten ist. Der Name fist dem Pronomen 'it' im Englischen sehr ähnlich - es ist ein Platzhalter, der fast alles bedeuten kann. Wir wissen nicht, was 'es' ist, bis wir es in einem Satz verwenden, und wir wissen nicht, was fist, bis wir anrufen fold.

Wenn wir Dinge benennen, wollen wir so viele Informationen wie möglich aus dem Namen herausholen, und wir bevorzugen, dass der Name kurz ist (wenn wir das bekommen können, ohne wichtige Informationen zu opfern). Hier haben wir einen sehr kurzen Namen, der uns fast alles sagt, was wir darüber wissen. Ich denke nicht, dass es verbessert werden kann.

Wird in der imperativen Programmierung ials Schleifenzähler verwendet (wie jund k, wenn wir mehr benötigen); wird in der funktionalen Programmierung ffür ein Funktionsargument in Funktionen höherer Ordnung verwendet (wie gund h, wenn wir mehr benötigen). Ich habe nicht genug Erfahrung mit funktionalen Sprachen, um sicherzugehen, dass die f / g / h-Konvention genauso gut etabliert ist wie die i / j / k-Konvention, aber wenn nicht, denke ich, sollte es so sein (es ist definitiv so) in der Mathematik etabliert).


3

Der gebräuchlichste Name dafür, den ich außer dem Pronomen gehört habe f, ist binary operationoder binary function- das Problem, spezifischer zu sein, ist, dass er buchstäblich alles kann , und deshalb halten sich die Leute an die Typensignatur a -> b -> a(oder a -> b -> bwenn es richtig ist) .

Also schlage ich vor, dass Sie genau das tun, sich an die Typensignatur halten, zum Glück hat diese bestimmte Typensignatur einen Namen: binary functionGenau wie a -> aa unary operationund a -> ba unary functionkönnen Sie a -> a -> aa binary operationund a -> b -> ca nennen binary function.


1
Für mich binary operationwürde mehr bedeuten a -> a -> aund binary functionwürde stehen für a -> b -> c... die Wahrheit liegt sicherlich dazwischen. :-)
user40989

@ user40989 guter Anruf, korrigiert.
Jimmy Hoffa

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.