“具体化”是什么?和“具体化”在(函数式?)编程的上下文中意味着什么?

发布于 2024-10-22 05:41:01 字数 274 浏览 4 评论 0原文

我在有关 haskell 和函数式编程的博客中读过很多这个术语(特别是在 sigfpe 的博客 中),但我不知道了解它的含义。大多数时候我都不知道,但如果我知道的话,我可能会更好地理解这些文本。谷歌没有帮助我。我迷失在技术方面。

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

我对计算机科学概念的理解有点慢,所以带有代码的实际示例会很好。 :P

I read this term a lot in blogs about haskell and functional programming (specially in sigfpe's blog) but I don't have a clue about what it means. I get away with not knowing it most of the times, but I probably would have understood the texts a lot better if I knew. Google didn't help me. I get lost in the technical stuff.

Also the non-technical meaning of the world ("turning the abstract concrete") doesn't help me understand what it practically means to reify something in code.

I'm kinda slow with computer science concepts, so practical examples with code would be nice. :P

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

手心的温暖 2024-10-29 05:41:01

所以我读了这篇文章,这几乎就是它的意思:采用抽象概念并将其具体化。或者,有一个代表抽象概念的代理。例如,在 Lisp 中,当您使用 lambda 时,过程抽象和应用的概念就会具体化。

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

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

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

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

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

根据 Paul Graham 在 Hackers & 中的报道画家,p。 185、麦卡锡说:“史蒂夫·拉塞尔说,看,我为什么不编写这个评估......,我对他说,嗬,嗬,你把理论与实践混淆了,这个评估是为了阅读,而不是为了阅读。”但他继续这样做了,那就是,他将我论文中的 eval 编译成 IBM 704 机器代码,修复了 bug,然后将其宣传为 Lisp 解释器,而在那时 Lisp 确实做到了。本质上就是它今天的形式……”

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

So I read up on this, and it is pretty much what it means: taking an abstract concept and making it concrete. Or, there is a proxy that represents the abstract concept. For example, in Lisp, the concept of procedure abstraction and application is reified when you use lambdas.

Reification by itself is a broad concept and not just applicable to functional programming-languages.

In Java for example, there are types that are available at runtime. These are reifiable types. Meaning, there exists a concrete representation of the abstract concept of the type, during runtime. In contrast, there are non-reifiable types. This is especially evident during the use of generics in Java. In Java, generics are subject to type erasure, and so generic type-information is not available during runtime (unless the parameterized type uses unbounded wildcards).

Another example is when you try to model a concept. For example, assume that you have a Group class and a User class. Now there are certain abstract concepts that describe the relationship between the two. For example, the abstract concept of a User being the member of a Group. To make this relationship concrete, you would write a method called isMemberOf that says whether a User is a member of a Group. So what you've done here is that you have reified (made real/explicit/concrete) the abstract concept of group membership.

Another good example is a database where you have parent-child relationships between objects. You can describe this relationship in the abstract concept of a tree. Now suppose you have a function/method that takes this data from the database and constructs an actual Tree object. What you've now done is reified the abstract concept of the parent-child tree-like relationship into an actual Tree object.

Coming back to functional languages in general, perhaps the best example of reification is the creation of the Lisp programming language itself. Lisp was a completely abstract and theoretical construct (basically just a mathematical notation for computer languages). It remained that way until Lisp's eval function was actually implemented by Steve Russel on an IBM 704:

According to what reported by Paul Graham in Hackers & Painters, p. 185, McCarthy said: "Steve Russell said, look, why don't I program this eval..., and I said to him, ho, ho, you're confusing theory with practice, this eval is intended for reading, not for computing. But he went ahead and did it. That is, he compiled the eval in my paper into IBM 704 machine code, fixing bug , and then advertised this as a Lisp interpreter, which it certainly was. So at that point Lisp had essentially the form that it has today..."

So Lisp was reified from an abstract concept, into an actual programming language.  

飘过的浮云 2024-10-29 05:41:01

具体化

具体化是实例化的一种形式。当您具体化一个概念时,您会将抽象的东西变得具体,就像您提供的字典定义一样。

您可以选择将类型具体化为居住在某些可能类型的抽象语法树中的术语。

您可以通过为某种语言提出通用的实现来具体化设计模式。例如,类似

template<typename T> class Singleton {
    public:
        static T& Instance() {
            static T me;
            return me;
        }

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

将单例设计模式具体化为 C++ 中的模板。

您可以将霍尔的快速排序思想具体化为您选择的编程语言的实现。本着这种精神,我花了很多时间将范畴论中的概念具体化为 Haskell 代码。

您可以将一种语言具体化为该语言的解释器。 Larry Wall 对 Perl 语言的想法被具体化为 Perl 解释器。

data-reifyvacuum 包将术语具体化为图表,表示它如何通过共享在内存中构建。

反思

具体化的另一面是反思,它采用具体的东西,并通常通过忘记一些细节来生成抽象。也许您想这样做是因为抽象更简单,或者以某种方式捕获了您所讨论内容的本质。

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

就像如何将编程语言具体化为实现一样,有时您可能会走向相反的方向。尽管这通常被认为是一个坏主意,但您可能会采取一种实现并尝试从其行为的所需属性反映语言规范。 TeX 首先由 Knuth 实现,没有规范。 TeX 的任何规范都已从 Knuth 的实现中反映出来。

如果您将反射视为一个健忘的函子,它将您从具体领域带到抽象领域,那么理想情况下,具体化是左伴随反射。)

(更正式地说, 我维护的 /package/reflection" rel="noreferrer">reflection 包提供了一个 reify 方法,它接受一个术语并生成一个表示它的类型,然后是一个 Reflect 方法,让您生成一个新术语。这里的“具体”域是类型系统,抽象域是术语。

Reification

Reification is a form of instantiation. When you reify a concept, you take something abstract and make it concrete, just like the dictionary definition you provided.

You might choose to reify a type as a term inhabiting some abstract syntax tree of possible types.

You might reify a design pattern by coming up with a general purpose implementation of it for some language. For instance, something like

template<typename T> class Singleton {
    public:
        static T& Instance() {
            static T me;
            return me;
        }

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

reifies the singleton design pattern as a template in C++.

You can reify Hoare's idea of quicksort into an implementation in the programming language of your choice. In this vein, I spend a lot of time reifying concepts from category theory into Haskell code.

You can reify a language as an interpreter for that language. Larry Wall's idea of Perl the language is reified as the perl interpreter.

The data-reify and vacuum packages reify terms as graphs representing how it is structured in memory with sharing.

Reflection

The flip side of reification is reflection, which takes something concrete, and generates an abstraction, usually by forgetting some details. Perhaps you want to do this because the abstraction is simpler, or somehow captures the essence of what you are talking about.

Type-system reflection in Java, C#, etc. takes a concrete class in a programming language, and provides you with the abstract structure a class, giving you access to the list of what members your classes provide. Here we are taking the concrete notion of a type, and generating an abstract term out of it that describes its structure, while discarding any particular values.

Like how you can reify a programming language into an implementation, you may some times go in the opposite direction. Though this is generally considered a bad idea, you might take an implementation and try to reflect a language specification from the desirable properties of its behavior. TeX was implemented first by Knuth, sans specification. Any specification of TeX has been reflected from Knuth's implementation.

(More formally if you view reflection as a forgetful functor that takes you from a concrete domain to an abstract domain, then reification is, ideally, left adjoint to reflection.)

The reflection package I maintain provides a reify method that takes a term and yields a type that represents it, then a reflect method that lets you generate a new term. Here the 'concrete' domain is the type system, and the abstract domain are terms.

小女人ら 2024-10-29 05:41:01

来自 Haskell Wiki

“具体化”某物就是采取
抽象和尊重的东西
它作为材料。一个经典的例子是
古人采取的方式
抽象概念(例如“胜利”)和
将他们变成神(例如耐克,
希腊胜利女神)。

具体化类型是一个值
代表一种类型。使用具体化类型
而不是真正的类型意味着你
可以对它们进行任何操作
你可以用价值观来做到这一点。

From the Haskell Wiki:

To "reify" something is to take
something that is abstract and regard
it as material. A classic example is
the way that the ancients took
abstract concepts (e.g. "victory") and
turned them into deities (e.g. Nike,
the Greek goddess of victory).

A reified type is a value that
represents a type. Using reified types
instead of real types means that you
can do any manipulations with them
that you can do with values.

情绪失控 2024-10-29 05:41:01

我能想到的一个用途(我确信还有其他用途!)是将类变成字典。让我们以 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 ->;一个-> Bool,您将获得 ..By 函数,例如 Data.List.nubBy 和朋友 - 与 Ord 类似的技巧> 通向 Data.List.sortBy

One use I can think of (I'm sure there are others!) is turning a class into a dictionary. Let's take the Eq class (forgetting about the /= operator for the moment):

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

If we reify this class, it becomes:

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

which can be constructed, inspected and so on. Also noteworthy is that you can have only one Eq instance per type, but multiple EqDict values. But the automatic construction of instances (e.g. getting equality for lists when you have it for elements) doesn't work; you'll have to construct the EqDict [a] value yourself.

The reifying process is as simple as this (for this case):

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

A function using the Eq class could transform something like this:

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

If you unwrap the EqDict and just pass an a -> a -> Bool, you're getting the ..By functions, like Data.List.nubBy and friends - a similar trick for Ord leads to Data.List.sortBy.

十年不长 2024-10-29 05:41:01

即使仅在 Haskell 的上下文中,该术语的使用也非常广泛。 Andy Gill 的 reify 包允许您采用递归结构并将它们转换为显式图。 Sigpfe 关于延续的帖子描述了将“计算的其余部分”的概念具体化为可以传递的值。 Template Haskell 有一个 reify 函数(通常在编译时与 TH 代码一起执行),当给定 Haskell 值的名称时,该函数返回有关该值的可用信息(声明位置、类型等)。

所有这些案例有什么共同点?他们谈论的是采用一些我们可以推理和知道但我们无法直接以编程方式操作的东西,并将其转变为我们可以像其他值一样命名和传递的实际一流值。这通常是人们使用这个词时想要传达的意图。

Even just in the context of Haskell the term is used very broadly. Andy Gill's reify package allows you to take recursive structures and turn them into explicit graphs. Sigpfe's post on continuations describes reifying the notion of "the rest of the computation" into a value you can pass around. Template Haskell has a reify function (executed, along with TH code in general, at compile time) that when given the name of a Haskell value returns available information on it (where declared, type, etc.).

What do all these cases have in common? They're talking about taking something which we can reason about and know, but which we can't directly programmatically manipulate, and turning it into an actual first class value that we can name and pass around just like any other. And that's generally the intent that people want to convey when they use the word.

沩ん囻菔务 2024-10-29 05:41:01

我知道RDF中有具体化的概念。正如 Tim Bernes-Lee Tim Bernes-Lee 所说:

在这种情况下,具体化意味着使用该语言以某种语言表达某些事物,以便该语言可以处理该事物。

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

I know there's the concept of reification in RDF. As stated by Tim Bernes-Lee:

Reification in this context means the expression of something in a language using the language, so that it becomes treatable by the language.

I suppose it's kind of like reflection or introspection. I hope you get some good answers here!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文