Haskell 撤消数据库中的记录

Haskell 撤消数据库中的记录,haskell,functional-programming,Haskell,Functional Programming,我正在创建一个系统,该系统需要存储用户在数据库中运行的所有函数和参数。没有记录会被删除,但我需要能够重新创建最小的函数序列和参数集,以便进行确定性的重新生成 用户交互非常少,它们不是编程输入交互,是在C++中处理的,通过FFI作为数据,积聚成列表,回调处理当前的数据缓冲区。该函数触发一系列关于如何连接数据库中数据集的处理图的决策,以及这些数据集的输入函数。这个图是非循环的。此图最初运行,并为用户显示值。图的后面部分将被重新组合以生成新的图 这些图的Haskell内部结构是通过分析数据库中的数据和

我正在创建一个系统,该系统需要存储用户在数据库中运行的所有函数和参数。没有记录会被删除,但我需要能够重新创建最小的函数序列和参数集,以便进行确定性的重新生成

<>用户交互非常少,它们不是编程输入交互,是在C++中处理的,通过FFI作为数据,积聚成列表,回调处理当前的数据缓冲区。该函数触发一系列关于如何连接数据库中数据集的处理图的决策,以及这些数据集的输入函数。这个图是非循环的。此图最初运行,并为用户显示值。图的后面部分将被重新组合以生成新的图

这些图的Haskell内部结构是通过分析数据库中的数据和组合中的简单随机选择创建的。我希望能够存储一个随机生成器的种子,它所应用的模块和参数id

我认为最好将EDSL的功能存储在数据库中,在数据库中只存储高级交互,但完全确定

我对存储值不感兴趣,而是对操作的函数图感兴趣

每个表引用不同的函数。每个记录都有一个日期和一个任务ID,用于将特定操作的所有函数分组以获取。参数引用表ID和记录ID。如果组合函数在内部执行生成随机数之类的操作,则应自动存储该数字的种子

我使用的是没有GHCI和持久SQlite的GHC阶段1


我仍然是Haskell的新手,希望了解什么方法和包适合以功能性的方式解决此问题。

如果您希望对源代码级函数执行此操作,例如:

myFoo x y = x + y
除非你想在编译器中进行黑客攻击,否则你就太倒霉了。但是,您可以定义自己的函数概念,并使用一些合适的注释来支持这一点。让我们把这个概念称为
UserAction a
,其中
a
是操作的返回类型。为了在
UserAction
中组合计算,它应该是
Monad
。不要想得太多,我的第一印象是使用这堆monad变形金刚:

type UserAction = WriterT [LogEntry] (ReaderT FuncIdentifier IO)
WriterT[LogEntry]
组件表示
UserAction
在运行时会生成一系列
LogEntry
s[1],其中包含要写入数据库的信息;比如:

data LogEntry = Call FuncIdentifier FuncIdentifier
userAction func action = do
    caller <- ask
    -- record the current call
    tell [Call caller func]
    -- Call the body of this action, passing the current identifier as its caller.
    local (const func) action
现在可以推迟存储随机种子、任务标识符等,这可以通过向
LogEntry
中添加信息来整合到这个设计中

ReaderT FuncIdentifier
组件表示
UserAction
依赖于
FuncIdentifier
;即调用它的函数的标识符

FuncIdentifier
可以通过以下简单的方法实现

type FuncIdentifier = String
或者,如果你喜欢的话,你可以使用更具结构的东西

IO
组件说
UserAction
s可以对文件、控制台、生成线程等进行任意输入和输出。如果您的操作不需要此功能,请不要使用它(改用
Identity
)。但既然你提到生成随机数,我想你脑子里并没有纯粹的计算[2]

然后,您可以使用如下函数对要记录日志的每个操作进行注释:

userAction :: FuncIdentifier -> UserAction a -> UserAction a
这将是这样使用的:

randRange :: (Integer, Integer) -> UserAction Integer
randRange (low,hi) = userAction "randRange" $ do
    -- implementation
userAction
将记录呼叫并设置被呼叫方记录呼叫;e、 g.类似于:

data LogEntry = Call FuncIdentifier FuncIdentifier
userAction func action = do
    caller <- ask
    -- record the current call
    tell [Call caller func]
    -- Call the body of this action, passing the current identifier as its caller.
    local (const func) action
userAction func action=do

调用方“函数图”是什么意思?GHC Haskell将运行时系统中的函数表示为一个图(运行时是一个所谓的图归约机),但用户无法访问其内部。在数据库中存储函数将非常复杂-通常这是“持久”语言(如Napier 88或Tycoon-2)的领域。Napier 88的持久化存储(persistent Haskell)上已经实现了Haskell,但这是一个早已完成的研究项目。抱歉,这有点不清楚。我和哈斯克尔的关系还不稳定。我将用我认为可能是我需要的策略来重新表述这个问题。我现在正在输入。用户与哪种API交互?您的问题不断变化!这种方法不太适合确定性的重新生成——主要是因为
UserAction
类型中的
IO
。我认为我们需要更多地了解您对这个框架的预期用途,以帮助进行确定性再生——如果您不使用
IO
,Haskell是纯粹的确定性的,因此您可能不需要做任何事情,只需记录计算的输入。我已经更新了这个问题。EDSL可能不是正确的方法,在这种情况下,我将删除这一方面-在黑暗中拍摄一点。