SQL 数据库和函数式编程不一致吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/330371/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Are Databases and Functional Programming at odds?
提问by Tristan Havelick
I've been a web developer for some time now, and have recently started learning some functional programming. Like others, I've had some significant trouble apply many of these concepts to my professional work. For me, the primary reason for this is I see a conflict between between FP's goal of remaining stateless seems quite at odds with that fact that most web development work I've done has been heavily tied to databases, which are very data-centric.
我做 Web 开发人员已有一段时间了,最近开始学习一些函数式编程。和其他人一样,我在将许多这些概念应用于我的专业工作时遇到了一些重大问题。对我来说,主要原因是我看到 FP 保持无状态的目标与我所做的大多数 Web 开发工作都与非常以数据为中心的数据库密切相关的事实之间存在冲突。
One thing that made me a much more productive developer on the OOP side of things was the discovery of object-relational mappers like MyGeneration d00dads for .Net, Class::DBI for perl, ActiveRecord for ruby, etc. This allowed me to stay away from writing insert and select statements all day, and to focus on working with the data easily as objects. Of course, I could still write SQL queries when their power was needed, but otherwise it was abstracted nicely behind the scenes.
让我在 OOP 方面成为更有效率的开发人员的一件事是发现了对象关系映射器,例如用于 .Net 的 MyGeneration d00dads、用于 perl 的 Class::DBI、用于 ruby 的 ActiveRecord 等。这让我能够远离从整天编写插入和选择语句,到专注于将数据作为对象轻松处理。当然,当需要 SQL 查询的能力时,我仍然可以编写 SQL 查询,但除此之外,它在幕后被很好地抽象出来。
Now, turning to functional-programming, it seems like with many of the FP web frameworks like Links require writing a lot of boilerplate sql code, as in this example. Weblocks seems a little better, but it seems to use kind of an OOP model for working with data, and still requires code to be manually written for each table in your database as in this example. I suppose you use some code generation to write these mapping functions, but that seems decidedly un-lisp-like.
现在,转向函数式编程,似乎像 Links 这样的许多 FP web 框架需要编写大量样板 sql 代码,如本例所示。Weblocks 看起来好一点,但它似乎使用了一种 OOP 模型来处理数据,并且仍然需要为数据库中的每个表手动编写代码,如本例所示。我想您使用一些代码生成来编写这些映射函数,但这似乎完全不像 lisp。
(Note I have not looked at Weblocks or Links extremely closely, I may just be misunderstanding how they are used).
(注意我没有非常仔细地查看 Weblocks 或 Links,我可能只是误解了它们的使用方式)。
So the question is, for the database access portions (which I believe are pretty large) of web application, or other development requiring interface with a sql database we seem to be forced down one of the following paths:
所以问题是,对于 Web 应用程序的数据库访问部分(我认为相当大),或其他需要与 sql 数据库接口的开发,我们似乎被迫采用以下路径之一:
- Don't Use Functional Programming
- Access Data in an annoying, un-abstracted way that involves manually writing a lot of SQL or SQL-like code ala Links
- Force our functional Language into a pseudo-OOP paradigm, thus removing some of the elegance and stability of true functional programming.
- 不要使用函数式编程
- 以一种烦人的、非抽象的方式访问数据,包括手动编写大量 SQL 或类似 SQL 的代码 ala Links
- 强制我们的函数式语言进入伪 OOP 范式,从而消除真正函数式编程的一些优雅和稳定性。
Clearly, none of these options seem ideal. Has found a way circumvent these issues? Is there really an even an issue here?
显然,这些选项似乎都不理想。有没有找到绕过这些问题的方法?这里真的有问题吗?
Note: I personally am most familiar with LISP on the FP front, so if you want to give any examples and know multiple FP languages, lisp would probably be the preferred language of choice
注意:我个人最熟悉 FP 方面的 LISP,所以如果你想举任何例子并了解多种 FP 语言,lisp 可能是首选语言
PS: For Issues specific to other aspects of web development see this question.
PS:对于特定于 Web 开发其他方面的问题,请参阅此问题。
采纳答案by Svante
First of all, I would not say that CLOS (Common Lisp Object System) is "pseudo-OO". It is first class OO.
首先,我不会说 CLOS(Common Lisp Object System)是“伪 OO”。这是一流的OO。
Second, I believe that you should use the paradigm that fits your needs.
其次,我认为您应该使用适合您需求的范式。
You cannot statelessly store data, while a function is flow of data and does not really need state.
你不能无状态地存储数据,而函数是数据流,并不真正需要状态。
If you have several needs intermixed, mix your paradigms. Do not restrict yourself to only using the lower right corner of your toolbox.
如果您有多种混合需求,请混合使用您的范例。不要限制自己只能使用工具箱的右下角。
回答by HLGEM
Coming at this from the perspective of a database person, I find that front end developers try too hard to find ways to make databases fit their model rather than consider the most effective ways to use database which are not object oriented or functional but relational and using set-theory. I have seen this generally result in poorly performing code. And further it creates code that is difficult to performance tune.
从数据库人员的角度来看,我发现前端开发人员太努力地寻找使数据库适合他们模型的方法,而不是考虑使用数据库的最有效方法,这些方法不是面向对象的或功能性的,而是关系型的集合论。我已经看到这通常会导致代码性能不佳。此外,它还创建了难以进行性能调整的代码。
When considering database access there are three main considerations - data integrity (why all business rules should be enforced at the database level not through the user interface), performance, and security. SQL is written to manage the first two considerations more effectively than any front end language. Because it is specifically designed to do that. The task of a database is far different than the task of a user interface. Is it any wonder that the type of code that is most effective in managing the task is conceptually different?
在考虑数据库访问时,有三个主要考虑因素 - 数据完整性(为什么所有业务规则都应该在数据库级别而不是通过用户界面执行)、性能和安全性。编写 SQL 是为了比任何前端语言更有效地管理前两个注意事项。因为它是专门为此而设计的。数据库的任务与用户界面的任务大不相同。在管理任务时最有效的代码类型在概念上是不同的,这有什么奇怪的吗?
And databases hold information critical to the survival of a company. Is is any wonder that businesses aren't willing to experiment with new methods when their survival is at stake. Heck many businesses are unwilling to even upgrade to new versions of their existing database. So there is in inherent conservatism in database design. And it is deliberately that way.
数据库保存对公司生存至关重要的信息。难怪企业在生存受到威胁时不愿意尝试新方法。哎呀,许多企业甚至不愿意升级到现有数据库的新版本。所以在数据库设计中存在固有的保守性。而且是故意这样的。
I wouldn't try to write T-SQL or use database design concepts to create your user-interface, why would you try to use your interface language and design concepts to access my database? Because you think SQL isn't fancy (or new) enough? Or you don't feel comfortable with it? Just because something doesn't fit the model you feel most comfortable with, doesn't mean it is bad or wrong. It means that it is different and probably different for a legitimate reason. You use a different tool for a different task.
我不会尝试编写 T-SQL 或使用数据库设计概念来创建您的用户界面,为什么您会尝试使用您的界面语言和设计概念来访问我的数据库?因为您认为 SQL 不够花哨(或新)?或者你觉得不舒服?仅仅因为某些东西不适合您感觉最舒服的模型,并不意味着它是坏的或错误的。这意味着它是不同的,并且可能出于合法原因而不同。您使用不同的工具执行不同的任务。
回答by Kevin Albrecht
You should look at the paper "Out of the Tar Pit" by Ben Moseley and Peter Marks, available here: "Out of the Tar Pit" (Feb. 6, 2006)
您应该查看 Ben Moseley 和 Peter Marks 的论文“Out of the Tar Pit”,可在此处获得:“Out of the Tar Pit”(2006 年 2 月 6 日)
It is a modern classic which details a programming paradigm/system called Functional-Relational Programming. While not directly relating to databases, it discusses how to isolate interactions with the outside world (databases, for example) from the functional core of a system.
它是现代经典,详细介绍了称为函数关系编程的编程范式/系统。虽然与数据库没有直接关系,但它讨论了如何将与外部世界(例如数据库)的交互与系统的功能核心隔离开来。
The paper also discusses how to implement a system where the internal state of the application is defined and modified using a relational algebra, which obviously is related to relational databases.
论文还讨论了如何实现一个系统,其中使用关系代数定义和修改应用程序的内部状态,这显然与关系数据库有关。
This paper will not give an an exact answer to how to integrate databases and functional programming, but it will help you design a system to minimize the problem.
本文不会给出如何集成数据库和函数式编程的确切答案,但它会帮助您设计一个系统来最小化问题。
回答by J. Abrahamson
Functional languages do not have the goal to remain stateless, they have the goal to make management of state explicit. For instance, in Haskell, you can consider the State monad as the heart of "normal" state and the IO monad a representation of state which must exist outside of the program. Both of these monads allow you to (a) explicitly represent stateful actions and (b) build stateful actions by composing them using referentially transparent tools.
You reference a number of ORMs, which, per their name, abstract databases as sets of objects. Truely, this is not what the information in a relational database represents! Per its name, it represents relational data. SQL is an algebra (language) for handling relationships on a relational data set and is actually quite "functional" itself. I bring this up so as to consider that (a) ORMs are not the only way to map database information, (b) that SQL is actually a pretty nice language for some database designs, and (c) that functional languages often have relational algebra mappings which expose the power of SQL in an idiomatic (and in the case of Haskell, typechecked) fashion.
函数式语言的目标不是保持无状态,它们的目标是使状态管理变得明确。例如,在 Haskell 中,您可以将 State monad 视为“正常”状态的核心,而 IO monad 则是必须存在于程序之外的状态表示。这两个 monad 都允许您 (a) 显式表示有状态操作和 (b) 通过使用引用透明工具组合它们来构建有状态操作。
您引用了许多 ORM,根据它们的名称,它们将数据库抽象为对象集。确实,这不是关系数据库中的信息所代表的!顾名思义,它代表关系数据。SQL 是一种用于处理关系数据集上的关系的代数(语言),它本身实际上非常“实用”。我提出这个是为了考虑 (a) ORM 不是映射数据库信息的唯一方法,(b) SQL 对于某些数据库设计来说实际上是一种非常好的语言,以及 (c) 函数式语言通常具有关系代数映射以惯用的方式(在 Haskell 的情况下,经过类型检查)展示 SQL 的强大功能。
I would say most lisps are a poor man's functional language. It's fully capable of being used according to modern functional practices, but since it doesn't require them the community is less likely to use them. This leads to a mixture of methods which can be highly useful but certainly obscures how pure functional interfaces can still use databases meaningfully.
我会说大多数 lisps 都是穷人的函数式语言。它完全能够根据现代功能实践使用,但由于它不需要它们,社区不太可能使用它们。这导致了多种方法的混合,这些方法可能非常有用,但肯定会掩盖纯函数式接口仍然可以有意义地使用数据库的方式。
回答by Mendelt
I don't think the stateless nature of fp languages is a problem with connecting to databases. Lisp is a non-pure functional programming language so it shouldn't have any problem dealing with state. And pure functional programming languages like Haskell have ways of dealing with input and output that can be applied to using databases.
我不认为 fp 语言的无状态特性是连接数据库的问题。Lisp 是一种非纯函数式编程语言,因此处理状态应该没有任何问题。像 Haskell 这样的纯函数式编程语言有处理输入和输出的方法,可以应用于使用数据库。
From your question it seems like your main problem lies in finding a good way to abstract away the record-based data you get back from your database into something that is lisp-y (lisp-ish?) without having to write a lot of SQL code. This seems more like a problem with the tooling/libraries than a problem with the language paradigm. If you want to do pure FP maybe lisp isn't the right language for you. Common lisp seems more about integrating good ideas from oo, fp and other paradigms than about pure fp. Maybe you should be using Erlang or Haskell if you want to go the pure FP route.
从您的问题来看,您的主要问题似乎在于找到一种好方法,将您从数据库中获取的基于记录的数据抽象为 lisp-y(lisp-ish?),而无需编写大量 SQL代码。这似乎更像是工具/库的问题,而不是语言范式的问题。如果您想做纯 FP,也许 lisp 不是适合您的语言。Common lisp 似乎更多地是关于整合来自 oo、fp 和其他范式的好主意,而不是纯粹的 fp。如果你想走纯 FP 路线,也许你应该使用 Erlang 或 Haskell。
I do think the 'pseudo-oo' ideas in lisp have their merit too. You might want to try them out. If they don't fit the way you want to work with your data you could try creating a layer on top of Weblocks that allows you to work with your data the way you want. This might be easier than writing everything yourself.
我确实认为 lisp 中的“伪 oo”想法也有其优点。您可能想尝试一下。如果它们不适合您想要处理数据的方式,您可以尝试在 Weblocks 之上创建一个层,以允许您以想要的方式处理数据。这可能比自己编写所有内容更容易。
Disclaimer: I'm not a Lisp expert. I'm mostly interested in programming languages and have been playing with Lisp/CLOS, Scheme, Erlang, Python and a bit of Ruby. In daily programming life I'm still forced to use C#.
免责声明:我不是 Lisp 专家。我对编程语言最感兴趣,并且一直在玩 Lisp/CLOS、Scheme、Erlang、Python 和一些 Ruby。在日常编程生活中,我仍然被迫使用 C#。
回答by animal
If your database doesn't destroy information, then you can work with it in a functional manner consistent with "pure functional" programming values by working in functions of the entire database as a value.
如果您的数据库不破坏信息,那么您可以通过将整个数据库的函数作为值来处理,以与“纯函数”编程值一致的函数方式使用它。
If at time T the database states that "Bob likes Suzie", and you had a function likes which accepted a database and a liker, then so long as you can recover the database at time T you have a pure functional program that involves a database. e.g.
如果在时间 T 数据库声明“Bob 喜欢 Suzie”,并且您有一个函数 like 接受了一个数据库和一个喜欢者,那么只要您可以在时间 T 恢复数据库,那么您就有了一个涉及数据库的纯函数程序. 例如
# Start: Time T
likes(db, "Bob")
=> "Suzie"
# Change who bob likes
...
likes(db "Bob")
=> "Alice"
# Recover the database from T
db = getDb(T)
likes(db, "Bob")
=> "Suzie"
To do this you can't ever throw away information you might use (which in all practicality means you cannot throw away information), so your storage needs will increase monotonically. But you can start to work with your database as a linear series of discrete values, where subsequent values are related to the prior ones through transactions.
为此,您永远不能丢弃可能使用的信息(这实际上意味着您不能丢弃信息),因此您的存储需求将单调增加。但是您可以开始使用您的数据库作为离散值的线性系列,其中后续值通过事务与先前值相关联。
This is the major idea behind Datomic, for example.
例如,这是Datomic背后的主要思想。
回答by ConcernedOfTunbridgeWells
Not at all. There are a genre of databases known as 'Functional Databases', of which Mnesiais perhaps the most accessible example. The basic principle is that functional programming is declarative, so it can be optimised. You can implement a join using List Comprehensionson persistent collections and the query optimiser can automagically work out how to implement the disk access.
一点也不。有一类数据库称为“功能数据库”,其中Mnesia可能是最容易访问的示例。基本原则是函数式编程是声明式的,因此可以对其进行优化。您可以在持久集合上使用List Comprehensions实现连接,查询优化器可以自动计算出如何实现磁盘访问。
Mnesia is written in Erlangand there is at least one web framework (Erlyweb) available for that platform. Erlang is inherently parallel with a shared-nothing threading model, so in certain ways it lends itself to scalable architectures.
Mnesia 是用Erlang编写的,并且至少有一个 Web 框架 ( Erlyweb) 可用于该平台。Erlang 本质上与无共享线程模型并行,因此在某些方面它适用于可扩展架构。
回答by Honza Pokorny
I'm most comfortable with Haskell. The most prominent Haskell web framework (comparable to Rails and Django) is called Yesod. It seems to have a pretty cool, type-safe, multi-backend ORM. Have a look at the Persistance chapterin their book.
我对 Haskell 最满意。最著名的 Haskell Web 框架(可与 Rails 和 Django 相媲美)称为 Yesod。它似乎有一个非常酷的、类型安全的、多后端 ORM。看看他们书中的持久性章节。
回答by Fried Brice
A database is the perfect way to keep track of state in a stateless API. If you subscribe to REST, then your goal is to write stateless code that interacts with a datastore (or some other backend) that keeps track of state information in a transparent way so that your client doesn't have to.
数据库是在无状态 API 中跟踪状态的完美方式。如果您订阅 REST,那么您的目标是编写与数据存储(或某个其他后端)交互的无状态代码,该代码以透明方式跟踪状态信息,以便您的客户端不必这样做。
The idea of an Object-Relational Mapper, where you import a database record as an object and then modify it, is just as applicable and useful to functional programming as it is to object oriented programming. The one caveat is that functional programming does not modify the objectin place, but the database API can allow you to modify the recordin place. The control flow of your client would look something like this:
Object-Relational Mapper 的想法是将数据库记录作为对象导入然后修改它,它对于函数式编程和面向对象编程一样适用和有用。一个警告是,函数式编程不会就地修改对象,但数据库 API 可以让您就地修改记录。您的客户端的控制流程如下所示:
- Import the record as an object (the database API can lock the record at this point),
- Read the object and branch based on its contents as you like,
- Package a new object with your desired modifications,
- Pass the new object to the appropriate API call which updates the record on the database.
- 将记录作为对象导入(此时数据库API可以锁定记录),
- 根据需要读取对象和分支,根据其内容,
- 用您想要的修改打包一个新对象,
- 将新对象传递给更新数据库记录的相应 API 调用。
The database will update the record with your changes. Pure functional programming might disallow reassigning variables within the scope of your program, but your database API can still allow in-place updates.
数据库将根据您的更改更新记录。纯函数式编程可能不允许在您的程序范围内重新分配变量,但您的数据库 API 仍然可以允许就地更新。
回答by Lin Pengcheng
Databases and Functional Programming can be fused.
数据库和函数式编程可以融合。
for example:
例如:
Clojure is a functional programming language based on relational database theory.
Clojure 是一种基于关系数据库理论的函数式编程语言。
Clojure -> DBMS, Super Foxpro
STM -> Transaction,MVCC
Persistent Collections -> db, table, col
hash-map -> indexed data
Watch -> trigger, log
Spec -> constraint
Core API -> SQL, Built-in function
function -> Stored Procedure
Meta Data -> System Table
Note: In the latest spec2, spec is more like RMDB. see: spec-alpha2 wiki: Schema-and-select
注意:在最新的 spec2 中,spec 更像是 RMDB。请参阅:spec-alpha2 wiki:Schema-and-select
I advocate: Building a relational data model on top of hash-map to achieve a combination of NoSQL and RMDB advantages. This is actually a reverse implementation of posgtresql.
我主张:在hash-map之上构建关系数据模型,实现NoSQL和RMDB优势的结合。这实际上是 posgtresql 的反向实现。
Duck Typing: If it looks like a duck and quacks like a duck, it must be a duck.
鸭子打字:如果它看起来像一只鸭子并且叫起来像一只鸭子,那么它一定是一只鸭子。
If clojure's data model like a RMDB, clojure's facilities like a RMDB and clojure's data manipulation like a RMDB, clojure must be a RMDB.
如果 clojure 的数据模型像 RMDB,clojure 的工具像 RMDB,Clojure 的数据操作像 RMDB,那么 clojure 必须是 RMDB。
Clojure is a functional programming language based on relational database theory
Implement relational data model and programming based on hash-map (NoSQL)