Проверка на разбирането на: Променлива v.s. Стойност и функция срещу абстракция

(Този въпрос е продължение на този докато изучаване на Haskell.)

Преди намирах понятието между „променлива“ и „стойност“ за объркващо. Затова прочетох за уики страницата на ламбда смятане, както и за предишния отговор по-горе. Излизам с интерпретации по-долу.

Мога ли да потвърдя дали те са правилни? Просто искам да потвърдя двойно, защото тези концепции са доста основни, но съществени за функционалното програмиране. Всеки съвет е добре дошъл.

Предпоставки от wiki:

Синтаксис на Lambda Calculus
exp → ID
| (exp)
| λ ID.exp // абстракция
| exp exp // приложение

(Нотация: "‹=>" еквивалентно на)

Тълкувания:

  1. "стойност": това са действителните данни или инструкции, съхранени в компютъра.
    "променлива": това е начин за локализиране на данните, препратка, заместваща стойност, но не самият набор от данни или инструкции, съхранени в компютъра.< br> "абстракция" ‹=> "функция" ∈ синтактична форма. (https://stackoverflow.com/a/25329157/3701346)
    „приложение“: отнема вход на "абстракция" и въвеждане на "ламбда израз", води до "ламбда израз".
    "абстракция" се нарича "абстракция", защото в обичайната дефиниция на функция съкращаваме (обикновено по-дългото) тяло на функцията в много по-кратка форма, т.е. идентификатор на функция, последван от списък с формални параметри. (Въпреки че ламбда абстракциите са анонимни функции, други функции обикновено имат име.)

  2. "променлива" ‹=> "символ" ‹=> "препратка"
    "променлива" се свързва със "стойност" чрез процес, наречен "обвързване".

  3. "константа" ∈ "променлива"
    "литерал" ∈ "стойност"
    "формален параметър" ∈ "променлива"
    "действителен параметър"(аргумент) ∈ "стойност"

  4. „Променлива“ може да има „стойност“ на „данни“ => напр. променливата "a" има стойност 3

  5. „Променлива“ може също да има „стойност“ на „набор от инструкции“ => напр. операторът "+" е променлива

person modeller    schedule 25.08.2014    source източник
comment
"literal" ∈ "value" Бих казал, че това не е правилно. Стойността е нещо, което съществува по време на изпълнение и е конкретна дата (както казахте). Литералът е специфична синтактична конструкция. Това е нещо, което казва на анализатора каква стойност да създаде, но не е самата стойност.   -  person Felix Kling    schedule 26.08.2014
comment
@FelixKling, хубаво е да го знам. Мислех, че сред всички синтактични конструкции, литералът е този, който е най-близо до value.   -  person modeller    schedule 26.08.2014


Отговори (2)


"стойност": това са действителните данни или инструкции, съхранени в компютъра.

Опитваш се да мислиш за това много конкретно от гледна точка на машината, което се опасявам, че може да те обърка. По-добре е да мислите за това от гледна точка на математиката: стойността е просто нещо, което никога не се променя, като числото 42, буквата „H“ или последователността от букви, които представляват „Здравей свят“.

Друг начин да мислим за това е от гледна точка на ментални модели. Ние измисляме умствени модели, за да разсъждаваме индиректно за света; разсъждавайки върху менталните модели, ние правим прогнози за нещата в реалния свят. Ние пишем компютърни програми, които да ни помогнат да работим с тези умствени модели надеждно и в големи обеми.

Тогава ценностите са неща в менталния модел. Битовете и байтовете са само кодирания на модела в архитектурата на компютъра.

"променлива": това е начин за локализиране на данните, референция за заместване на стойност, но не и самия набор от данни или инструкции, съхранени в компютъра.

Променливата е просто име, което означава стойност в определен обхват на програмата. Всеки път, когато се оценява променлива, нейната стойност трябва да се търси в среда. Има няколко реализации на тази концепция в компютърна гледна точка:

  • Рамка на стека в един нетърпелив език е реализация на среда за търсене на стойностите на локална променлива при всяко извикване на рутина.
  • Линкерът осигурява среди за търсене на имена в глобален обхват, когато дадена програма се компилира или зарежда в паметта.

"абстракция" ‹=> "функция" ∈ синтактична форма.

Абстракцията и функцията не са еквивалентни. В ламбда смятането "абстракция" е вид синтактичен израз, но функцията е стойност.

Една аналогия, която не е твърде изтъркана, е имена и описания срещу неща. Имената и описанията са част от езика, докато нещата са част от света. Може да се каже, че значението на име или описание е нещото, което то назовава или описва.

Езиците съдържат както прости имена за неща (напр. 12 е име за числото дванадесет), така и по-сложни описания на нещата (5 + 7 е описание на числото дванадесет). Ламбда абстракцията е описание на функция; например изразът \x -> x + 7 е описание на функцията, която добавя седем към своя аргумент.

Номерът е, че когато описанията станат много сложни, не е лесно да разберете какво описват. Ако ви дам 12345 + 67890, трябва да свършите малко работа, за да разберете какво число описах току-що. Компютрите са машини, които вършат тази работа много по-бързо и по-надеждно, отколкото ние можем да я направим.

"приложение": отнема въвеждане на "абстракция" и въвеждане на "ламбда израз", което води до "ламбда израз".

Приложението е просто израз с два подизраза, който описва стойност по този начин:

  1. Първият подизраз означава функция.
  2. Вторият подизраз означава някаква стойност.
  3. Приложението като цяло означава стойността, която се получава при прилагане на функцията в (1) към стойността от (2).

Във формалната семантика (и не се плашете от тази дума) ние често използваме двойните скоби ⟦∙⟧, за да обозначим "значението на"; напр. ⟦dog⟧ = "значението на куче." Използвайки тази нотация:

⟦e1 e2⟧ = ⟦e1⟧(⟦e2⟧)

където e1 и e2 са всеки два израза или термина (всяка променлива, абстракция или приложение).

„абстракцията“ се нарича „абстракция“, защото в обичайната дефиниция на функция съкращаваме (обикновено по-дългото) тяло на функцията в много по-кратка форма, т.е. идентификатор на функция, последван от списък с формални параметри. (Въпреки че ламбда абстракциите са анонимни функции, други функции обикновено имат име.)

Да ви кажа честно, никога не съм спирал да мисля дали терминът "абстракция" е добър термин за това или защо е избран. Като цяло, с математиката не си струва да задавате такива въпроси, освен ако термините не са подбрани много зле и подвеждат хората.

"константа" ∈ "променлива"

"литерал" ∈ "стойност"

Ламбда смятането, само по себе си, няма понятията "константа", нито "литерал". Но един от начините да ги дефинирате би бил:

  • Литералът е израз, който поради правилата на езика винаги има една и съща стойност, независимо къде се среща.
  • Константата, на чисто функционален език, е променлива в най-горния обхват на програмата. Всяко (незасенчено) използване на тази променлива винаги ще има същата стойност в програмата.

"формален параметър" ∈ "променлива"

"действителен параметър" (аргумент) ∈ "стойност"

Формалният параметър е един вид използване на променлива. Във всеки израз от формата λv.e (където v е променлива, а e е израз), v е формална променлива.

Аргумент е всеки израз (не стойност!), който се появява като втори подизраз на приложение.

„Променлива“ може да има „стойност“ на „данни“ => напр. променливата "a" има стойност 3

Всички изрази имат стойности, а не само променливи. Например 5 + 7 е приложение и има стойност дванадесет.

„Променлива“ може също да има „стойност“ на „набор от инструкции“ => напр. операторът "+" е променлива

Стойността на + е функция — това е функцията, която добавя своите аргументи. Наборът от инструкции е имплементация на тази функция.

Мислете за функция като за абстрактна таблица, която казва за всяка комбинация от стойности на аргумент какъв е резултатът. Начинът, по който идват инструкциите, е следният:

  1. За много функции не можем буквално да ги реализираме като таблица. В случай на добавяне това е, защото таблицата ще бъде безкрайно голяма.
  2. Дори за функции, където можем да изброим случаите, искаме да ги внедрим много по-кратко и по-ефективно.

Но начинът, по който проверявате дали изпълнението на функция е правилно, е в известен смисъл да проверите дали във всеки случай тя прави същото, което би направила „безкрайната таблица“. Два набора инструкции, които се проверяват по този начин, всъщност са две различни реализации на една и съща функция.

person Luis Casillas    schedule 26.08.2014
comment
Направих още няколко четения относно моделите за оценка, за да разбера по-добре горната концепция. Цялостното изображение вече става по-ясно и аз също дойдох с няколко по-трудни въпроса тук stackoverflow.com/questions/25666056/ . Ще съм благодарен, ако може да се сподели някакво просветление. - person modeller; 04.09.2014

  1. Думата „абстракция“ се използва, защото не можем да „погледнем вътре“ в дадена функция и да видим какво се случва в по-голямата си част, така че тя е „абстрактна“ (за разлика от „конкретна“). Приложението е процес на прилагане на функция към аргумент. Това означава, че тялото му се изпълнява, но нещото, което се прилага към него, замества името на аргумента (избягвайки всякакво улавяне). Надяваме се, че този пример ще обясни по-добре, отколкото мога (в синтаксиса на Haskell. \ представлява ламбда): (\x -> x + x) 5 <=> 5 + 5 Тук прилагаме ламбда израза отляво към стойността 5 отдясно. Получаваме 5 + 5 като резултат (който след това може да бъде допълнително намален до 10). „Препратка“ може да се отнася до нещо малко по-различно в контекста на Haskell (IORefs и STRefs), но вътрешно всички обвързвания („променливи“) в Haskell имат слой на индиректност като препратки в други езици (всъщност те дори имат повече индиректност от това в известен смисъл поради нестриктната оценка).

  2. Това в повечето случаи изглежда добре, с изключение на референтния проблем, който споменах по-горе.

    • В Haskell всъщност няма разлика между променлива и константа.

    • „Литералът“ обикновено е конкретно конструктор за стойност. Например 20 конструира числото 20, но функционално приложение (\x -> 2 * x) 10 няма да се счита за литерал за 20, защото има допълнителна стъпка, преди да получите стойността.

    • Вярно, не всички променливи са параметри. Параметърът е нещо, което се предава на функция. xs в ламбда изразите по-горе са примери за параметри. Непример би бил нещо като let a = 15 in a * a. a е "променлива", но не и параметър. Всъщност бих нарекъл a "обвързване" тук, защото никога не може да се промени или да приеме различна стойност (варира).

    • Формалният параметър спрямо частта с действителния параметър изглежда горе-долу правилен.

  3. Това изглежда добре.

  4. Бих казал, че променливата може да бъде функция вместо това. Обикновено във функционалното програмиране ние обикновено мислим от гледна точка на функции и функционални приложения вместо списъци с инструкции.

Бих искал също така да отбележа, че може да имате проблеми, като мислите за функциите просто като за синтактични форми. Можете да създавате нови функции, като прилагате определени видове функции от по-висок ред, без да използвате някоя от синтактичните форми за директно конструиране на функция. Прост пример за това е композицията на функцията, (.) в Haskell

(f . g) x = f (g x)   -- Definition of (.)

(* 10) . (+ 1)    <=>   \x -> ((* 10) ((+ 1) x))   <=>   \x -> 10 * (x + 1)

Записването му като (* 10) . (+ 1) не използва директно ламбда синтаксиса или синтаксиса на дефиницията на функцията за създаване на новата функция.

person David Young    schedule 25.08.2014