【问题标题】:Getting the results of a Haskell script from Java从 Java 获取 Haskell 脚本的结果
【发布时间】:2013-12-09 15:22:26
【问题描述】:

我正在尝试创建一个程序来比较各种 haskell 脚本运行所需的时间,稍后将用于创建图形并显示在 GUI 中。我尝试使用 Haskell 库创建所述 GUI,但运气不佳,特别是因为我无法找到适用于 Windows 的最新 GUI 库。我尝试使用 Java 来获得这些结果,但要么返回错误,要么根本没有结果。

我构建了一个最小的示例来大致展示我目前正在做的事情:

    import java.io.*;
public class TestExec {
    public static void main(String[] args) {
        try {
            Process p = Runtime.getRuntime().exec("ghc test.hs 2 2");
            BufferedReader in = new BufferedReader(
                                new InputStreamReader(p.getInputStream()));
            String line = null;
            while ((line = in.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

这是调用的 Haskell 脚本,在本例中是一个简单的添加:

test x y =  x + y

目前根本没有存储或打印任何结果。有人有什么想法吗?

【问题讨论】:

  • 先创建可执行文件,然后在exec中运行
  • 你的haskell代码中还需要一个main
  • 你告诉 Haskell test x yx + y 是一样的。你期望什么输出?
  • 你也应该使用runghc而不是ghc
  • 这样的基准测试不会产生任何可靠的结果。 “测试”功能立即执行。因此,您的基准测试只会衡量您的操作系统启动可执行文件需要多长时间。

标签: java haskell


【解决方案1】:

由于您尝试将其作为可执行文件运行,因此您需要提供一个 main.在你的情况下,它应该看起来像

import System.Environment

test :: Integer -> Integer -> Integer
test = (+)

main = do
  [x, y] <- map read `fmap` getArgs
  print $ x `test` y

这只是读取命令行参数,添加它们,然后打印它们。虽然我之前做过类似的事情,但在 Haskell 中进行基准测试/测试,并将输出数据以更结构化的格式转储到文本文件中,然后用 Java 或您喜欢的任何语言解析/显示它要容易得多。

【讨论】:

  • 我在尝试编译时遇到错误:无法将类型 [Char] 与 Char 匹配,预期类型 IO 字符串,实际类型 IO [字符串](在 fmap 的第二个参数中) .我曾考虑让一个 Haskell 脚本为目录中的每个其他脚本执行所有基准测试等,但不确定它是否比这种方式更简单。不过,我可能会回头看看,谢谢你的提示
  • 谢谢。我认为不需要另一个完整问题的另一个快速问题:使用上面发布的代码的变体,我想读取两个参数,但一个是字符串,另一个是整数,但是编译时出现类型不匹配错误。有没有办法告诉 haskell 将 X 读取为 Int 并将 y 读取为 String?
  • @fylth 删除 map read 部分,而不是 test x ytest (read x) y
【解决方案2】:

这主要是一个 Java 问题。搜索Runtime.getRuntime().exec()

在 Haskell 方面,您需要编写一个独立的 Haskell 脚本。 @jozefg 的The one 可以。你应该可以运行它

runghc /path/to/script.hs 1 2

从命令行。

从 Java 调用它与在 Java 中运行任何其他外部进程没有什么不同。在 Clojure(一种 JVM 语言,为了简洁起见,我使用它)我这样做:

user=> (def p (-> (Runtime/getRuntime) (.exec "/usr/bin/runghc /tmp/test.hs 1 2")))
#'user/p
user=> (-> p .getInputStream input-stream reader line-seq)
("3")

请注意,我使用runghc 运行脚本(不是ghc)。完整路径不是必需的,但可能会有所帮助。您的 Java 程序可以这样修改:

--- TestExec.question.java
+++ TestExec.java
@@ -2,7 +2,7 @@
 public class TestExec {
     public static void main(String[] args) {
         try {
-            Process p = Runtime.getRuntime().exec("ghc test.hs 2 2");
+            Process p = Runtime.getRuntime().exec("/usr/bin/runghc /tmp/test.hs 2 2");
             BufferedReader in = new BufferedReader(
                                 new InputStreamReader(p.getInputStream()));
             String line = null;

修改后的版本可以很好地运行 Haskell 脚本。您可能需要更改指向您 runghctest.hs 位置的路径。

【讨论】:

    【解决方案3】:

    首先要从输出中读取,您需要使用OutputStreamReader(p.getOutputStream()) 而不是InputStreamReader

    【讨论】:

      【解决方案4】:

      正如我在评论中所说,这样的基准是完全不正确的。虽然基准测试应该消除尽可能多的侧面海岸。最好的解决方案是使用criterion 包。它可以根据您的需要生成漂亮的图形输出。

      小例子:

      import Criterion
      import Criterion.Main
      import Criterion.Config
      
      fac 1 = 1
      fac n = n * (fac $ n-1)
      
      myConfig = defaultConfig {
                    cfgReport = ljust "report.html"
                   }
      
      main = defaultMainWith myConfig (return ()) [
                 bench "fac 30" $ whnf fac 30
                ]
      

      执行后,它会生成一个文件“report.html”,其中包含整洁的交互式绘图。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-26
        • 1970-01-01
        • 2011-02-22
        • 2010-10-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多