从 Python 生成 运行 Haskell 代码
Generating and running Haskell code from Python
我们正在编写一个 python 程序,试图在给定输入输出对的情况下合成一个(简单的)haskell 函数。在整个 运行 程序中,我们生成 haskell 代码并根据用户提供的示例检查其正确性。
假设我们得到输入“1 2”和预期输出“3”。我们会(最终)
提出加号功能。然后我们会 运行
(\x y -> x + y) 1 2
in haskell 并检查它的计算结果是否为 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 都提前或在某个时间点运行,而是在我们生成代码时进行测试),同时允许我们使用多个语句(例如,导入)。
抱歉,如果其中任何一个是微不足道的或愚蠢的,我们将不胜感激。
这似乎是一件奇怪的事情.. 但 有趣 none 更少。
这里立即想到两件事。首先是使用 ghci repl 而不是为每次 eval 尝试生成一个新进程。这个想法是将您的 I/O 流式传输到 ghci 进程中,而不是为每次尝试生成一个新的 ghc 进程。为每个 eval 启动一个新进程的开销似乎是性能杀手。我通常会选择 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()
这给了我非常一致的 >2x
速度提升。
有关更多信息,请参阅预期文档:https://github.com/pexpect/pexpect/
第二个直接的想法是使用一些分布式计算。我没有时间在这里构建完整的演示,但是互联网和 SO 领域已经有很多很好的例子。这个想法是让多个 "python + ghci" 进程从公共队列读取 eval attempts
,然后将结果推送到公共 eval attempt checker
。我对 ghc(i) 了解不多,但快速检查表明 ghci 是一个多线程进程,因此这可能需要多台机器才能完成,每台机器并行尝试不同的尝试子集。
此处可能感兴趣的一些链接:
How to use multiprocessing queue in Python?
https://docs.python.org/2/library/multiprocessing.html
https://eli.thegreenplace.net/2012/01/24/distributed-computing-in-python-with-multiprocessing
我们正在编写一个 python 程序,试图在给定输入输出对的情况下合成一个(简单的)haskell 函数。在整个 运行 程序中,我们生成 haskell 代码并根据用户提供的示例检查其正确性。
假设我们得到输入“1 2”和预期输出“3”。我们会(最终)
提出加号功能。然后我们会 运行
(\x y -> x + y) 1 2
in haskell 并检查它的计算结果是否为 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 都提前或在某个时间点运行,而是在我们生成代码时进行测试),同时允许我们使用多个语句(例如,导入)。
抱歉,如果其中任何一个是微不足道的或愚蠢的,我们将不胜感激。
这似乎是一件奇怪的事情.. 但 有趣 none 更少。
这里立即想到两件事。首先是使用 ghci repl 而不是为每次 eval 尝试生成一个新进程。这个想法是将您的 I/O 流式传输到 ghci 进程中,而不是为每次尝试生成一个新的 ghc 进程。为每个 eval 启动一个新进程的开销似乎是性能杀手。我通常会选择 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()
这给了我非常一致的 >2x
速度提升。
有关更多信息,请参阅预期文档:https://github.com/pexpect/pexpect/
第二个直接的想法是使用一些分布式计算。我没有时间在这里构建完整的演示,但是互联网和 SO 领域已经有很多很好的例子。这个想法是让多个 "python + ghci" 进程从公共队列读取 eval attempts
,然后将结果推送到公共 eval attempt checker
。我对 ghc(i) 了解不多,但快速检查表明 ghci 是一个多线程进程,因此这可能需要多台机器才能完成,每台机器并行尝试不同的尝试子集。
此处可能感兴趣的一些链接:
How to use multiprocessing queue in Python?
https://docs.python.org/2/library/multiprocessing.html
https://eli.thegreenplace.net/2012/01/24/distributed-computing-in-python-with-multiprocessing