在(功能性?)编程的背景下,“reify”和“具体化”意味着什么?

时间:2011-03-15 16:36:23

标签: haskell functional-programming metaprogramming terminology reification

我在关于haskell和函数式编程的博客中经常阅读这个术语(特别是在sigfpe's blog中),但我对它的含义并不了解。我大部分时间都不知道,但如果我知道,我可能会更好地理解文本。谷歌没有帮助我。我迷失在技术方面。

此外,世界的非技术含义(“改变抽象具体”)并不能帮助我理解在代码中实现内容的实际意义。

我对计算机科学概念有点慢,所以使用代码的实际例子会很好。 :P

6 个答案:

答案 0 :(得分:36)

所以我读到了这个,它几乎意味着什么:采用抽象概念并使其具体化。或者,有一个代表抽象概念的代理。例如,在Lisp中,当使用lambdas时,程序抽象和应用程序的概念就会被实现。

具体化是一个广泛的概念,不仅适用于函数式编程语言。

例如,在Java中,有些类型在运行时可用。这些是可再生的类型。意思是,在运行时期间,存在类型的抽象概念的具体表示。相反,存在不可再生类型。在Java中使用泛型时尤其明显。在Java中,泛型需要进行类型擦除,因此在运行时期间不能使用泛型类型信息(除非参数化类型使用无界通配符)。

另一个例子是当你尝试为一个概念建模时。例如,假设您有一个Group类和一个User类。现在有一些描述两者之间关系的抽象概念。例如,User的抽象概念是Group的成员。为了使这种关系具体化,您可以编写一个名为isMemberOf的方法,说明User是否是Group的成员。所以你在这里所做的就是你已经具体化(做出真实的/明确的/具体的)群体成员资格的抽象概念

另一个很好的例子是一个数据库,你在这个数据库中有对象之间的父子关系。您可以在树的抽象概念中描述此关系。现在假设您有一个函数/方法从数据库中获取此数据并构造一个实际的 Tree对象。您现在所做的是具体化将父子树状关系的抽象概念转换为实际 Tree对象。

回归一般的函数式语言,也许最好的具体化例子就是创建Lisp编程语言本身。 Lisp是一个完全抽象的理论构造(基本上只是计算机语言的数学符号)。它一直保持这种状态,直到Lisp的eval函数实际上由Steve Russel在IBM 704上实现:

根据Paul Graham在Hackers&画家,p。 185,麦卡锡说:“史蒂夫罗素说,看,为什么我不编程这个评估...,我告诉他,你好,你是理论与实践混淆,这个评估是为了阅读,而不是然而,他继续前进并做到了。也就是说,他将我的论文中的eval编译成IBM 704机器码,修复了bug,然后将其作为Lisp解释器进行了广告宣传。当然,Lisp有基本上它今天的形式......“

所以Lisp从一个抽象的概念具体化,变成一种实际的编程语言。

答案 1 :(得分:23)

<强>物化

具体化是一种实例化形式。当你理解一个概念时,你会采取一些抽象的东西并使其具体化,就像你提供的字典定义一样。

您可以选择将类型重新定义为居住在可能类型的抽象语法树中的术语。

您可以通过针对某种语言提出它的通用实现来实现设计模式。例如,像

这样的东西
template<typename T> class Singleton {
    public:
        static T& Instance() {
            static T me;
            return me;
        }

    protected:
       virtual ~Singleton() {};
       Singleton() {};
}

将单例设计模式作为C ++中的模板进行实现。

您可以将Hoare的quicksort想法变为您选择的编程语言中的实现。在这种情况下,我花了很多时间将类别理论中的概念用于Haskell代码。

您可以将语言用作该语言的翻译。拉里·沃尔(Larry Wall)对Perl语言的看法被称为perl解释器。

data-reifyvacuum软件包将术语表示为图形,表示在内存中如何通过共享进行结构化。

<强>反射

具体化的另一面是反射,它采取具体的东西,并通常通过忘记一些细节来生成抽象。也许你想这样做是因为抽象更简单,或者以某种方式捕捉到你所谈论的内容。

Java,C#等类型系统反射采用编程语言中的具体类,并为您提供类的抽象结构,使您可以访问类提供的成员列表。在这里,我们采用一种类型的具体概念,并从中生成描述其结构的抽象术语,同时丢弃任何特定值。

就像你如何将编程语言实现一个实现一样,有时可能会朝着相反的方向发展。虽然这通常被认为是一个坏主意,但您可以采用实现并尝试从其行为的理想属性反映语言规范。由Knuth开发的TeX 首先实现,没有规范。任何针对TeX的规范都反映在Knuth的实现中。

(更正式地说,如果你将反射视为一个将你从一个具体领域带到一个抽象领域的健忘仿函数,那么理想情况下,具体化就会与反射相伴随。)

我维护的reflection包提供了一个reify方法,它接受一个术语并产生一个表示它的类型,然后是一个反射方法,可以让你生成一个新术语。这里的“具体”域是类型系统,抽象域是术语。

答案 2 :(得分:21)

来自Haskell Wiki

  

要“改变”某事要采取   一些抽象和尊重的东西   它作为材料。一个典型的例子是   古人的方式   抽象概念(例如“胜利”)和   把他们变成了神灵(例如耐克,   希腊胜利女神)。

     

reified类型是一个值   代表一种类型。使用具体类型   而不是真正的类型意味着你   可以对他们进行任何操纵   你可以用价值观做。

答案 3 :(得分:14)

我能想到的一个用途(我确信还有其他用途!)正在将一个类变成一个字典。我们来看Eq课程(暂时忘记/=操作员):

class Eq a where
    (==) :: a -> a -> Bool

如果我们通知这个课程,那就变成了:

data EqDict a = EqDict (a -> a -> Bool)

可以构建,检查等。另外值得注意的是,每种类型只能有一个Eq个实例,但多个EqDict值。但是实例的自动构造(例如,当你为元素提供列表时获得相等)是行不通的;你必须自己构建EqDict [a]值。

通知过程就像这样简单(对于这种情况):

reify :: Eq a => EqDict a
reify = EqDict (==)

使用Eq类的函数可能会改变这样的事情:

-- 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 ]

如果您打开EqDict并只传递a -> a -> Bool,则会获得..By个功能,例如Data.List.nubBy和朋友 - Ord导致的Data.List.sortBy类似技巧{{1}}。

答案 4 :(得分:9)

即使只是在Haskell的背景下,该术语也被广泛使用。 Andy Gill的reify包允许您使用递归结构并将它们转换为显式图形。 Sigpfe关于延续的帖子描述了将“其余计算”的概念重新定义为可以传递的值。模板Haskell有一个reify函数(在编译时执行,通常与TH代码一起执行),当给定Haskell值的名称时,返回它的可用信息(声明,类型等)。

所有这些案件有什么共同之处?他们谈论的是采取我们可以推理和知道的东西,但我们不能直接以编程方式操作,并将其转化为我们可以像任何其他人一样命名和传递的实际的第一类值。这通常是人们在使用这个词时想要传达的意图。

答案 5 :(得分:2)

我知道RDF中存在着具体化的概念。正如stated by Tim Bernes-Lee

  

在此上下文中的具体化意味着使用该语言在某种语言中表达某些东西,以便它可以被语言处理。

我想这有点像反思或内省。我希望你能在这里得到一些好的答案!