从Python生成和运行Haskell代码

从Python生成和运行Haskell代码,python,haskell,ghc,ghci,Python,Haskell,Ghc,Ghci,我们正在编写一个python程序,试图在给定输入输出对的情况下合成一个(简单的)haskell函数。在整个程序运行过程中,我们生成haskell代码,并对照用户提供的示例检查其正确性。 假设我们得到输入“12”和预期输出“3”。我们会(最终) 提出加号函数。然后我们就跑 (\x y->x+y)1 2,并检查其计算结果是否为3 我们目前的做法是运行以下python代码: from subprocess import Popen, PIPE, STDOUT proccess = Popen(f'gh

我们正在编写一个python程序,试图在给定输入输出对的情况下合成一个(简单的)haskell函数。在整个程序运行过程中,我们生成haskell代码,并对照用户提供的示例检查其正确性。 假设我们得到输入“12”和预期输出“3”。我们会(最终) 提出加号函数。然后我们就跑
(\x y->x+y)1 2
,并检查其计算结果是否为3

我们目前的做法是运行以下python代码:

from subprocess import Popen, PIPE, STDOUT
proccess = Popen(f'ghc -e "{haskell_code}"', shell=True, stdout=PIPE, stderr=STDOUT) 
haskell_output = proc.stdout.read().decode('utf-8').strip('\n')
由于我们两人都不熟悉ghc、haskell、流程或与之相关的任何东西,我们希望有人能帮助我们以(更)高效的方式完成这项任务,因为目前进展非常缓慢

此外,我们希望能够执行多条语句。例如,我们希望导入Data.Char,以便我们的函数可以使用“toUpper”。但是,我们目前的做法是发送一个lambda函数及其附加的输入,我们不确定如何在上面添加导入语句(添加“\n”似乎不起作用)

总而言之,我们想要最快的(运行时)解决方案,它允许我们从python测试haskell函数(我们没有提前或在某个时间点测试所有haskell函数的代码,而是在生成代码时进行测试),同时允许我们使用多个语句(例如,导入)


道歉如果这是琐碎或愚蠢的,任何帮助都将被高度赞赏

这似乎是一件奇怪的事情。。但还是很有趣

在这里,有两件事立刻浮现在我的脑海里。首先是使用ghci repl,而不是为每次评估尝试生成一个新流程。其思想是将I/O流式传输到ghci进程中,而不是为每次尝试生成一个新的ghc进程。为每个评估启动新流程的开销似乎是性能杀手。我通常会选择
expect
,但既然您想要python,我将调用
pexpect

import pexpect
import sys
from subprocess import Popen, PIPE, STDOUT
import time


REPL_PS = unicode('Prelude> ')
LOOPS = 100


def time_function(func):
    def decorator(*args, **kwargs):
        ts = time.time()
        func(*args, **kwargs)
        te = time.time()
        print "total time", (te - ts)
    return decorator


@time_function
def repl_loop():
    repl = pexpect.spawnu('ghci')
    repl.expect(REPL_PS)
    for i in range(LOOPS):
        repl.sendline('''(\\x y -> x + y) 1 2''')
        _, haskell_output = repl.readline(), repl.readline()
        repl.expect(REPL_PS)


@time_function
def subproc_loop():
    for i in range(LOOPS):
        proc = Popen('''ghc -e "(\\x y -> x + y) 1 2"''', shell=True, stdout=PIPE, stderr=STDOUT) 
        haskell_output = proc.stdout.read().decode('utf-8').strip('n')
        # print haskell_output


repl_loop()
subproc_loop()
这给了我2倍一致的速度提升

有关更多信息,请参见pexpect文档:

第二个直接的想法是使用一些分布式计算。我没有时间在这里构建完整的演示,但是已经有很多伟大的例子生活在互联网的土地上,等等。其思想是让多个“python+ghci”进程从公共队列中读取
eval尝试
,然后将结果推送到公共
eval尝试检查器
。我对ghc(I)了解不多,但快速检查表明ghci是一个多线程进程,所以这可能需要多台机器来完成,每台机器并行尝试不同的尝试子集

此处可能有一些感兴趣的链接:


IIRC
ghc-e
非常有限。您可以只使用
Data.Char.toUpper
完全限定,或者编写整个文件并
runghc
它。使用Data.Char.toUpper似乎可以解决第二个问题。然而,这需要我们使用完全限定的名称,而不是简单的“toUpper”。使用runghc会和ghc-e一样快,还是更快?感谢您的快速回复!