Haskell 如何向GHCi流程发送文本?

Haskell 如何向GHCi流程发送文本?,haskell,ghci,Haskell,Ghci,我正在工作。它正在GHCi中运行。我想创建一个函数,将语句输出到当前正在运行的GHCi会话。它必须在Linux和Mac上工作,不需要Windows。函数可能具有类型 executeStatement :: String -> IO () 我已经试过了: getProcessID和getParentProcessID然后发送 echo 'xxx' > /proc/92856/fd/1 -bash: /proc/92856/fd/1: No such file or director

我正在工作。它正在GHCi中运行。我想创建一个函数,将语句输出到当前正在运行的GHCi会话。它必须在Linux和Mac上工作,不需要Windows。函数可能具有类型

executeStatement :: String -> IO ()
我已经试过了:

  • getProcessID
    getParentProcessID
    然后发送

    echo 'xxx' > /proc/92856/fd/1
    -bash: /proc/92856/fd/1: No such file or directory
    
  • 我还尝试了
    runCommand
    ,但它在Bash中执行命令,而不是在GHCi中,所以我得到了一个错误,即找不到该命令

  • xdool
    不在mac上运行


您可以使用终端多路复用器在一个窗格中执行ghci,并从另一个窗格调用tmux命令,向ghci发送击键

允许您将文本加载到tmux剪贴板(当路径从stdin读取时使用
-

tmux粘贴缓冲区
用于将tmux剪贴板的内容粘贴到窗格中:

$ tmux list-panes
0: [127x24] [history 1850/2000, 1343570 bytes] %0
1: [127x24] [history 0/2000, 0 bytes] %2 (active)
$ tmux paste-buffer -t %0
注释中已经提到的另一个选项是使用库启动ghci进程,并通过管道标准输入发送命令

这里有一个小程序,它使用my helper包来处理过程(实际上不是必需的,您可以单独使用过程来处理)。stdin通过管道传输,stdout和stderr继承:

{-# LANGUAGE OverloadedStrings #-}

import System.Process.Streaming -- from process-streaming
import Pipes (lift,yield) -- from pipes
import Control.Concurrent (threadDelay)

main :: IO ()
main = executeInteractive program (feedProducer (do
    let delay = lift (threadDelay (1000000*6))
    delay
    yield "4 + 3\n"
    delay
    yield "5 + 3\n"))
  where
    program = (shell "ghci"){ std_in = CreatePipe }
输出为:

$ ./Main
GHCi, version 7.10.2: http://www.haskell.org/ghc/  :? for help
Prelude> 7
Prelude> 8
Prelude> Leaving GHCi.
您可以使用hackage中的项目来计算表达式。它们不会在当前正在运行的会话中进行计算,但您仍然可以在会话中发送表达式并读取其输出。 以下是一个例子:

import Language.Haskell.Ghcid

main :: IO ()
main = do 
    (g, _) <- startGhci "ghci" (Just ".") True 
    let executeStatement = exec g
    executeStatement "let x = 33"
    executeStatement "x + 8" >>= print . head
    executeStatement "print x" >>= print . head
    stopGhci g
import Language.Haskell.Ghcid
main::IO()
main=do
(g,)>=打印。头
executeStatement“打印x”>>=打印。头
斯托普吉
输出为“41”“33”,g表示ghci会话


如果你真的需要在已经运行的ghci实例中执行表达式,你可以看看这个函数,而不是创建一个新的进程,你必须进入现有进程,然后设置std_in、std_out和std_err。

除非“output”和“fd/1”都是打字错误,那么这与仅仅是
putStrLn
有什么不同呢?一般来说,您的最佳选择可能是使用
System.Process
运行您自己的GHCI流程,这将使您能够以(大部分)独立于平台的方式实际访问流程的标准输入和输出。这几乎肯定是与任何进程交互的最简单方式。您所说的“将语句输出到当前正在运行的GHCi会话”是什么意思还不是很清楚。您通常不会输出“语句”,不管它们是什么,您都会输出字符串。您可以将字符串输出到文件,而不是运行的程序。程序可能会读取管道,在这种情况下,您可以将某些内容输出到管道的另一端。但终端不是管道,没有“另一端”。(他们确实是这样做的,但你可能不想处理这种混乱;你的会话可能从终端读取,也可能不从终端读取)。你真正的目标是什么?您的用户应该看到/能够做什么?我从Scala程序中获得了灵感。我想在1点25分做这个。您会在幻灯片中看到一段代码(写入文本输出),当他运行r函数时,代码会从幻灯片复制到实际的scala解释器,并像他在那里写的一样进行计算。但scala有与解释器交互的库,IMO ghci没有。谢谢@user2407038的帮助。错别字在哪里?我明白问题所在——确实是错别字。您希望将输入发送到GHCI会话(即发送到我记忆中为fd0的stdin)。但是,将管道连接到
proc/../fd/.
的方法可能不起作用。如果希望运行由字符串表示的实际代码,则需要使用GHCAPI或类似的包装器。请注意,这不允许您与当前ghci进程交互(事实上,从解释器运行时很少工作),但您可以从应用程序启动ghci进程。谢谢,这看起来非常好。我需要当前会话,因为我希望用户能够更改0进行实时编码的内容。我要试一试
import Language.Haskell.Ghcid

main :: IO ()
main = do 
    (g, _) <- startGhci "ghci" (Just ".") True 
    let executeStatement = exec g
    executeStatement "let x = 33"
    executeStatement "x + 8" >>= print . head
    executeStatement "print x" >>= print . head
    stopGhci g