Як називається функціональний аргумент у складці


10

У функції вищого порядку скласти / зменшити, як називається функціональний аргумент, якщо такий є?

Я працюю над монадичною бібліотекою обробки табличних таблиць, де рядки складаються для отримання простих аналізів (наприклад, знаходження мінімального, максимального, середнього значення стовпця). Тому я шукаю звучну назву для аргументу foldфункції та будь-яке ім'я, яке добре знайшло своє значення у спільноті ML (або Haskell або Common Lisp як другий та третій кандидати) було б цікавим.

Ім'я на зразок fпоширене в описі foldфункцій, проте воно є ненаписаним і іменник краще підходить.


10
Немає жодної. Насправді, для катаморфізмів не існує навіть загальновживаного найменування (складка)
Daniel Gratzer

2
Якщо це питання до шкільного завдання чи іспиту, відповідь потрібно отримати від вчителя чи підручника, а не від нас. Він може називати це чимось іншим. Те, що викладають на уроці, - це не завжди те, що зазвичай використовується в реальному світі.
Роберт Харві

7
@RobertHarvey Це не екзаменаційне запитання (?) Чи щось подібне. Як програміст, я думаю, що вибір хороших імен для об'єктів програмування (типів, змінних тощо) є дуже важливим. І якщо щось має добре відоме ім'я, то немає ніяких причин не використовувати його, окрім незнання, і саме це питання.
user40989

9
@Izkata Ні, це неправильно. Функція вищого порядку - це функція, яка приймає функцію. foldє функцією вищого порядку. Аргумент складати - це лише те, аргумент
Даніель Гратцер

1
@jozefg Це як відповідь на другу частину вашого коментаря. Що стосується першої частини (та питання), дивіться мій пост про Meta. Їх називають процедурними параметрами.
Ізката

Відповіді:


8

Я не знаю, чи є на це однозначна відповідь, як згадував @jozefg. І так суто без міркувань, ось одне можливе пояснення:

Я підозрюю, що причина полягає в тому, що тип - наприклад, (a -> b -> b)у Haskellfoldr - є більш значущим, ніж будь-яке ім'я, яке можна придумати. Оскільки параметри aі bтипу можуть бути будь-якими , функція також може робити майже все, що завгодно. Таким чином , ви залишилися з такими іменами , як function, combiner, morphismі argument, які не є особливо значущими або. Можна також використовувати коротке, не відволікаюче ім’я.

Іншим прикладом є id :: a -> aфункція: як слід назвати його аргумент? Знову ж таки, я думаю id, що тип є більш описовим, ніж його назва аргументу.

Однак я згоден з вами - схоже, має бути загальна назва, можливо, в математиці. Сподіваюся, хтось може мене виправити з цього приводу.


Деякі приклади його назви в реальному коді:

У бібліотеках Haskell це здебільшого називається f(а іноді й operatorу коментарях):

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

Його також називають f у 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

Я не згоден з думкою, що fце неправильне ім'я для аргументу функції fold. Причина, за якою ми хочемо описові імена в програмуванні, полягає в тому, що ми знаємо, що описує це ім'я, і ​​це ім'я fзазвичай використовується в математиці (і функціональних мовах програмування) для функції (як є, так gі h).

Ми майже нічого не знаємо про це f(за задумом, оскільки якби ми могли бути більш конкретними щодо цього, ми б не могли використати foldяк багато речей), а назва fговорить нам про все, що нам потрібно знати, за винятком того, що це функція з двох аргументів. Назва fдуже схожа на займенник 'it' в англійській мові - це заповнювач, який може означати майже все. Ми не знаємо, що таке «це», поки не вживемо його у реченні, і не знаємо, що fє, поки не зателефонуємо fold.

Називаючи речі, ми хочемо отримати якомога більше інформації з імені, і ми вважаємо за краще, щоб ім’я було коротким (якщо ми можемо отримати це, не жертвуючи важливою інформацією). Тут у нас дуже коротке ім’я, яке говорить нам майже все, що ми знаємо про нього. Я не думаю, що це можна покращити.

В імперативному програмуванні iвикористовується як лічильник циклу (як є, jі k, якщо нам потрібно більше); у функціональному програмуванні fвикористовується для аргументу функції у функціях вищого порядку (як gі h, якщо нам потрібно більше). У мене немає достатнього досвіду роботи з функціональними мовами, щоб бути впевненим, що конвенція f / g / h настільки ж встановлена, як і конвенція i / j / k, але якщо це не так, я думаю, що має бути (це, безумовно, є встановлені з математики).


3

Найпоширеніша назва цього, про яку я чула, крім займенника f, binary operationабо binary function- проблема з тим, що бути більш конкретним, ніж це, це може зробити буквально все , і саме тому люди дотримуються підпису типу a -> b -> a(або a -> b -> bякщо це правильна складка) .

Тому я пропоную вам зробити саме це, ключку до типу підпису, на щастя , що тип конкретні підписи має ім'я: binary function, так само , як a -> aце unary operation, і a -> bце unary function, можна назвати і .a -> a -> abinary operationa -> b -> cbinary function


1
Для мене binary operationце означало б більше a -> a -> aі binary functionбуде виступати за a -> b -> c... правда, безумовно, лежить між ними. :-)
user40989

@ user40989 хороший дзвінок, виправлено.
Джиммі Хоффа

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.