Czytałem więc o tym, co to właściwie oznacza: przyjęcie abstrakcyjnej koncepcji i uczynienie jej konkretną. Lub istnieje proxy, które reprezentuje abstrakcyjne pojęcie. Na przykład w Lispie koncepcja abstrakcji procedury i aplikacji jest reifikowana, gdy używasz lambd.
Reifikacja sama w sobie jest pojęciem szerokim i nie ma zastosowania tylko do funkcjonalnych języków programowania.
Na przykład w Javie istnieją typy dostępne w czasie wykonywania. To są typy reifable. Oznacza to, że istnieje konkretna reprezentacja abstrakcyjnej koncepcji typu w czasie wykonywania. W przeciwieństwie do tego istnieją typy niewymienialne. Jest to szczególnie widoczne podczas używania typów ogólnych w Javie. W Javie typy generyczne podlegają wymazaniu typów, więc ogólne informacje o typie nie są dostępne w czasie wykonywania (chyba że sparametryzowany typ używa nieograniczonych symboli wieloznacznych).
Innym przykładem jest próba modelowania koncepcji. Na przykład załóżmy, że masz Group
klasę i User
klasę. Teraz istnieją pewne abstrakcyjne pojęcia, które opisują związek między nimi. Na przykład abstrakcyjne pojęcie User
bycia członkiem a Group
. Aby ta relacja była konkretna, napisałbyś metodę o nazwie, isMemberOf
która mówi, czy a User
jest członkiem a Group
. Więc to, co tutaj zrobiliście, to zreifikowanie ( urealnienie / wyraźne / konkretne) abstrakcyjnej koncepcji członkostwa w grupie.
Innym dobrym przykładem jest baza danych, w której istnieją relacje rodzic-dziecko między obiektami. Możesz opisać ten związek w abstrakcyjnym pojęciu drzewa. Teraz załóżmy, że masz funkcję / metodę, która pobiera te dane z bazy danych i konstruuje rzeczywisty Tree
obiekt. To, co teraz zrobiłeś, to ujednolicenie abstrakcyjnej koncepcji relacji drzewo rodzic-dziecko w rzeczywisty Tree
obiekt.
Wracając ogólnie do języków funkcjonalnych, być może najlepszym przykładem reifikacji jest stworzenie samego języka programowania Lisp. Lisp był konstruktem całkowicie abstrakcyjnym i teoretycznym (w zasadzie tylko matematyczną notacją języków komputerowych). Tak było, dopóki eval
funkcja Lispa nie została faktycznie zaimplementowana przez Steve'a Russela na IBM 704:
Zgodnie z tym, co napisał Paul Graham w Hackers & Painters, s. 185, McCarthy powiedział: „Steve Russell powiedział, spójrz, dlaczego nie zaprogramuję tego evalu… i powiedziałem mu, ho, ho, mylisz teorię z praktyką, ta ocena jest przeznaczona do czytania, a nie do obliczeń. Ale poszedł naprzód i zrobił to. To znaczy, skompilował eval w moim artykule do kodu maszynowego IBM 704, naprawił błąd, a następnie ogłosił to jako interpreter Lispa, którym z pewnością był. Więc w tym momencie Lisp miał zasadniczo forma, jaką ma dzisiaj… ”
Więc Lisp został zreifikowany z abstrakcyjnej koncepcji do rzeczywistego języka programowania.
Reifikacja
Reifikacja jest formą instancji. Kiedy reifikujesz pojęcie, bierzesz coś abstrakcyjnego i nadajesz mu konkret, tak jak podana definicja słownikowa.
Możesz zdecydować się na reifikację typu jako terminu zamieszkującego jakieś abstrakcyjne drzewo składniowe możliwych typów.
Możesz zreifikować wzorzec projektowy, wymyślając implementację ogólnego przeznaczenia w jakimś języku. Na przykład coś takiego
template<typename T> class Singleton { public: static T& Instance() { static T me; return me; } protected: virtual ~Singleton() {}; Singleton() {}; }
reifikuje pojedynczy wzorzec projektowy jako szablon w C ++.
Możesz przekształcić pomysł Hoare na szybkie sortowanie w implementację w wybranym języku programowania. W tym duchu spędzam dużo czasu na przekształcaniu koncepcji z teorii kategorii do kodu Haskella.
Możesz reifikować język jako tłumacz dla tego języka. Pomysł Larry'ego Walla na język Perl został zreifikowany jako interpreter perla.
Te dane-zreifikować i próżniowe opakowania zreifikować terminy jak wykresy reprezentujące jak jest skonstruowany w pamięci z dzielenia.
Odbicie
Drugą stroną urzeczowienia jest refleksja , która bierze coś konkretnego i generuje abstrakcję, zwykle zapominając o niektórych szczegółach. Być może chcesz to zrobić, ponieważ abstrakcja jest prostsza lub w jakiś sposób oddaje istotę tego, o czym mówisz.
Odbicie systemu typów w Javie, C # itp. Przyjmuje konkretną klasę w języku programowania i zapewnia abstrakcyjną strukturę klasy, dając dostęp do listy elementów członkowskich, które zapewniają te klasy. Tutaj bierzemy konkretne pojęcie typu i generujemy z niego abstrakcyjny termin, który opisuje jego strukturę, jednocześnie odrzucając jakiekolwiek określone wartości.
Podobnie jak w przypadku przekształcania języka programowania w implementację, czasami możesz pójść w przeciwnym kierunku. Chociaż jest to ogólnie uważane za zły pomysł, możesz wziąć implementację i spróbować odzwierciedlić specyfikację języka na podstawie pożądanych właściwości jego zachowania. TeX został zaimplementowany jako pierwszy przez Knutha, bez specyfikacji. Każda specyfikacja TeX została odzwierciedlona w implementacji Knutha.
(Bardziej formalnie, jeśli postrzegasz refleksję jako zapominalski funktor, który przenosi cię z domeny konkretnej do domeny abstrakcyjnej, wówczas reifikacja jest najlepiej pozostawiona w połączeniu z refleksją).
Odbicie pakiet utrzymuję zapewnia zreifikować metodę, która przyjmuje termin i dające rodzaj, który reprezentuje go, a następnie odbić metodę, która pozwala wygenerować nowy termin. W tym przypadku domena „konkretna” to system typów, a domena abstrakcyjna to terminy.
źródło
Z Haskell Wiki :
źródło
Jednym z zastosowań, które przychodzą mi do głowy (jestem pewien, że są inne!) Jest zamiana klasy w słownik. Weźmy
Eq
zajęcia (zapominając/=
na chwilę o operatorze):class Eq a where (==) :: a -> a -> Bool
Jeśli zreifikujemy tę klasę, stanie się ona:
data EqDict a = EqDict (a -> a -> Bool)
które można skonstruować, skontrolować i tak dalej. Warto również zauważyć, że możesz mieć tylko jedną
Eq
instancję na typ, ale wieleEqDict
wartości. Ale automatyczna konstrukcja instancji (np. Uzyskiwanie równości dla list, gdy masz ją dla elementów) nie działa; będziesz musiał sam skonstruowaćEqDict [a]
wartość.Proces reifikacji jest tak prosty (w tym przypadku):
reify :: Eq a => EqDict a reify = EqDict (==)
Funkcja korzystająca z
Eq
klasy może przekształcić coś takiego:-- silly example, doesn't really do anything findMatches :: Eq a => a -> [a] -> [a] findMatches x ys = [ y | y <- ys, x == y ] -- version using EqDict findMatchesDict :: EqDict a -> a -> [a] -> [a] findMatchesDict (EqDict f) x ys = [ y | y <- ys, f x y ]
Jeśli rozpakujesz EqDict i po prostu zdasz an
a -> a -> Bool
, otrzymasz..By
funkcje, likeData.List.nubBy
i friends - podobna sztuczka dlaOrd
potencjalnych klientówData.List.sortBy
.źródło
Nawet w kontekście Haskella termin ten jest używany bardzo szeroko. Pakiet reify Andy'ego Gilla pozwala na przyjmowanie struktur rekurencyjnych i przekształcanie ich w jawne wykresy. Post Sigpfe dotyczący kontynuacji opisuje przekształcenie pojęcia „reszty obliczeń” w wartość, którą można przekazać. Szablon Haskell ma funkcję reify (wykonywaną wraz z kodem TH w ogóle, w czasie kompilacji), która po podaniu nazwy wartości Haskell zwraca dostępne informacje o niej (gdzie został zadeklarowany, typ itp.).
Co łączy te wszystkie przypadki? Mówią o wzięciu czegoś, o czym możemy rozumować i o czym wiemy, ale nie możemy bezpośrednio programowo manipulować, i zmienić to w rzeczywistą wartość pierwszej klasy, którą możemy nazwać i przekazać tak jak każdą inną. I to jest generalnie intencja, którą ludzie chcą przekazać, używając tego słowa.
źródło
Wiem, że w RDF istnieje koncepcja reifikacji. Jak stwierdził Tim Bernes-Lee :
Przypuszczam, że to trochę jak refleksja lub introspekcja. Mam nadzieję, że otrzymałeś tutaj dobre odpowiedzi!
źródło