Quel est le nom de l'argument fonctionnel en pli


10

Dans la fonction d'ordre supérieur, repliez / réduisez quel est le nom, le cas échéant, de l'argument fonctionnel?

Je travaille sur une bibliothèque de traitement tabulaire monadique où les lignes sont pliées pour produire des analyses simples (comme trouver le minimum, le maximum, la moyenne d'une colonne). Je recherche donc un nom solide pour l'argument de la foldfonction et tout nom bien établi dans la communauté ML (ou Haskell ou Common Lisp comme deuxième et troisième candidats) serait intéressant.

Un nom comme fest commun dans la description des foldfonctions, il n'est cependant pas descriptif et un nom serait mieux adapté.


10
Il n'y en a pas. En fait, il n'y a même pas de nom universellement utilisé pour les catamorphismes (fold)
Daniel Gratzer

2
S'il s'agit d'une question pour un devoir scolaire ou un examen, vous devez obtenir la réponse de l'enseignant ou du manuel, pas de nous. Il l'appelle peut-être quelque chose de différent. Ce qui est enseigné en classe n'est pas toujours ce qui est couramment utilisé dans le monde réel.
Robert Harvey

7
@RobertHarvey Ce n'est pas une question d'examen (?) Ni rien de semblable. En tant que programmeur, je pense que choisir de bons noms pour programmer des objets (types, variables etc.) est très important. Et si quelque chose a un nom bien connu, alors il n'y a aucune raison de ne pas l'utiliser - à part l'ignorance, et c'est à cela que servent les questions.
user40989

9
@Izkata Non, c'est incorrect. Une fonction d'ordre supérieur est une fonction qui prend une fonction. foldest une fonction d'ordre supérieur. L'argument de se coucher est juste un ça, un argument
Daniel Gratzer

1
@jozefg Cela en réponse à la deuxième partie de votre commentaire. Quant à la première partie (et la question), voir mon post sur Meta. Ils sont appelés paramètres procéduraux.
Izkata

Réponses:


8

Je ne sais pas s'il y a une seule réponse à cela, comme l'a mentionné @jozefg. Et si purement par spéculation, voici une explication possible:

Je soupçonne que la raison en est que le type - (a -> b -> b)dans Haskellfoldr , par exemple - est plus significatif que n'importe quel nom que l'on pourrait trouver. Étant donné que les paramètres aet btype peuvent être n'importe quoi , la fonction peut également faire à peu près n'importe quoi. Donc , vous vous retrouvez avec des noms comme function, combiner, morphismet argumentqui ne sont pas particulièrement significatifs non plus . Autant utiliser un nom court et non distrayant.

Un autre exemple est la id :: a -> afonction: comment appeler son argument? Encore une fois, je pense que idle type de est plus descriptif que son nom d'argument.

Cependant, je suis d'accord avec vous - il semble qu'il devrait y avoir un nom commun, peut-être en mathématiques. J'espère que quelqu'un pourra me corriger à ce sujet.


Quelques exemples de son nom en vrai code:

Dans les bibliothèques de Haskell , il est principalement appelé f(et parfois operatordans les commentaires):

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

On l'appelle aussi f dans 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

Je ne suis pas d'accord avec l'idée que fc'est un mauvais nom pour l'argument de fonction de fold. La raison pour laquelle nous voulons des noms descriptifs dans la programmation est que nous savons ce que le nom décrit, et le nom fest couramment utilisé en mathématiques (et langages de programmation fonctionnels) pour une fonction (comme le sont get h).

Nous ne savons presque rien f(par conception, car si nous pouvions être plus précis à ce sujet, nous ne pourrions pas utiliser foldautant de choses), et le nom fnous dit tout ce que nous devons savoir, sauf qu'il est fonction de deux arguments. Le nom fressemble beaucoup au pronom «it» en anglais - c'est un espace réservé qui pourrait signifier presque n'importe quoi. Nous ne savons pas ce que c'est jusqu'à ce que nous l'utilisions dans une phrase, et nous ne savons pas ce que fc'est jusqu'à ce que nous appelions fold.

Lorsque nous nommons des choses, nous voulons obtenir autant d'informations que possible du nom, et nous préférons que le nom soit court (si nous pouvons l'obtenir sans sacrifier des informations importantes). Ici, nous avons un nom très court qui nous dit presque tout ce que nous savons à ce sujet. Je ne pense pas que cela puisse être amélioré.

En programmation impérative, iest utilisé comme compteur de boucles (comme le sont jet k, si nous en avons besoin de plus); en programmation fonctionnelle, fest utilisé pour un argument de fonction dans les fonctions d'ordre supérieur (comme le sont get h, si nous en avons besoin de plus). Je n'ai pas assez d'expérience avec les langages fonctionnels pour être sûr que la convention f / g / h est aussi bien établie que la convention i / j / k, mais si ce n'est pas le cas, je pense que ça devrait l'être (c'est certainement établie en mathématiques).


3

Le nom le plus courant pour cela que j'ai entendu autre que le pronom fserait binary operationou binary function- le problème d'être plus précis que cela est qu'il pourrait faire n'importe quoi , et c'est pourquoi les gens s'en tiennent à la signature de type a -> b -> a(ou a -> b -> bsi c'est le bon pli) .

Je vous propose donc de faire exactement cela, de vous en tenir à la signature de type, heureusement, cette signature de type spécifique a un nom:, binary functiontout comme a -> aest un unary operation, et a -> best un unary function, vous pouvez appeler a -> a -> aun binary operationet a -> b -> cun binary function.


1
Pour moi, binary operationcela signifierait plus a -> a -> aet binary functionreprésenterait a -> b -> c… la vérité se situe sûrement entre les deux. :-)
user40989

@ user40989 bon appel, corrigé.
Jimmy Hoffa

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.