Qual è il nome dell'argomento funzionale in piega

10

Nella funzione di ordine superiore piegare / ridurre qual è il nome, se esiste, di l'argomento funzionale?

Sto lavorando su una libreria di elaborazione tabellare monadica in cui le righe vengono piegate per produrre analisi semplici (come trovare il minimo, il massimo, la media di una colonna). Sto quindi cercando un nome per l'argomento della funzione fold e qualsiasi nome che sia ben consolidato nella comunità ML (o Haskell o Common Lisp come secondo e terzo candidato) sarebbe interessante.

Un nome come f è comune nella descrizione delle funzioni fold , è comunque non descrittivo e un nome sarebbe più adatto.

    
posta user40989 13.12.2013 - 17:22
fonte

4 risposte

8

Non so se c'è una sola risposta a questo, come ha detto @jozefg. E quindi per pura speculazione, ecco una possibile spiegazione:

Sospetto che il motivo sia dovuto al tipo - (a -> b -> b) in % has_conn% di Haskell , per esempio: è più significativo di qualsiasi altro nome che si possa immaginare. Poiché i parametri di tipo foldr e a potrebbero essere qualsiasi cosa , la funzione potrebbe fare praticamente qualsiasi cosa. Quindi ti rimangono nomi come b , function , combiner e morphism , che non sono particolarmente significativi. Potresti anche usare un nome breve e non distraente.

Un altro esempio è la funzione argument : come chiamare la sua argomentazione? Ancora una volta, penso che il tipo di id :: a -> a sia più descrittivo del suo nome argomento.

Tuttavia, sono d'accordo con te - sembra che ci dovrebbe essere un nome comune, forse in matematica. Spero che qualcuno possa correggermi su questo.

Alcuni esempi del suo nome in codice reale:

Nelle librerie di Haskell , è principalmente chiamato id (e talvolta f nei commenti):

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

Viene anche chiamato operator 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)))))
    
risposta data 31.01.2014 - 15:43
fonte
6

Non sono d'accordo con l'idea che f sia un brutto nome per l'argomento di funzione di fold . Il motivo per cui desideriamo nomi descrittivi nella programmazione è che sappiamo cosa descrive il nome e il nome f è comunemente usato in matematica (e nei linguaggi di programmazione funzionale) per una funzione (come g e h ).

Non conosciamo quasi nulla di f (in base alla progettazione, poiché se potessimo essere più specifici al riguardo, non potremmo utilizzare fold su tante cose), e il nome f ci dice tutto ciò di cui abbiamo bisogno sapere, tranne che è una funzione di due argomenti. Il nome f è molto simile al pronome 'it' in inglese - è un segnaposto che potrebbe significare quasi tutto. Non sappiamo che cosa sia "it" finché non lo usiamo in una frase e non sappiamo cosa sia f finché non chiamiamo fold .

Quando si nominano le cose, vogliamo ottenere quante più informazioni possibili dal nome e preferiamo che il nome sia breve (se riusciamo a ottenere ciò senza sacrificare informazioni importanti). Qui abbiamo un breve nome molto che ci dice quasi tutto ciò che sappiamo a riguardo. Non penso che possa essere migliorato.

Nella programmazione imperativa, i viene usato come contatore di loop (come j e k , se abbiamo bisogno di più); nella programmazione funzionale, f viene utilizzato per un argomento di funzione nelle funzioni di ordine superiore (come g e h , se abbiamo bisogno di più). Non ho abbastanza esperienza con i linguaggi funzionali per essere sicuro che la convenzione f / g / h sia ben stabilita come la convenzione i / j / k, ma se non lo è, penso che dovrebbe essere (è sicuramente stabilito in matematica).

    
risposta data 31.01.2014 - 17:50
fonte
3

Il nome più comune per questo che ho sentito oltre il pronome f sarebbe binary operation o binary function - il problema con l'essere più specifico di quello che potrebbe fare letteralmente qualsiasi cosa , ed è per questo che le persone si attaccano al tipo firma a -> b -> a (o a -> b -> b se è corretto).

Quindi ti propongo di fare esattamente questo, attenersi alla firma del tipo, fortunatamente quella specifica firma del tipo ha un nome: binary function , proprio come a -> a è un unary operation , e a -> b è un unary function , puoi chiamare a -> a -> a a binary operation e a -> b -> c a binary function .

    
risposta data 31.01.2014 - 18:12
fonte
1

La funzione richiesta viene a volte definita "funzione combinatoria" (vedi ad esempio la pagina HaskellWiki su Fold ), ma questo non è abbastanza comune per chiamarlo terminologia standard.

    
risposta data 05.10.2016 - 12:02
fonte

Leggi altre domande sui tag