gpt4 book ai didi

haskell - 在 JVM 上运行编译为 JavaScript 的 Haskell

转载 作者:行者123 更新时间:2023-12-04 02:26:09 28 4
gpt4 key购买 nike

Java 8 有一个名为 Nashorn 的内置 JavaScript 引擎,因此实际上可以在 JVM 上运行编译为 JavaScript 的 Haskell。

以下程序有效:

{-# LANGUAGE JavaScriptFFI #-}

module Main where

foreign import javascript unsafe "console={log: function(s) { java.lang.System.out.print(s); }}"
setupConsole :: IO ()

foreign import javascript unsafe "java.lang.System.exit($1)"
sysexit :: Int -> IO ()

main = do
setupConsole
putStrLn "Hello from Haskell!"
sysexit 0

我们可以通过以下方式运行它:(旁注:可以将其作为普通 Java 程序运行。 jjs 只是在 JVM 上运行纯 JavaScript 代码的一种便捷方式)
$ ghcjs -o Main Main.hs
[1 of 1] Compiling Main ( Main.hs, Main.js_o )
Linking Main.jsexe (Main)

$ which jjs
~/bin/jdk/bin/jjs

$ jjs Main.jsexe/all.js
Hello from Haskell!

在上面的代码中, console.log需要使用 java.lang.System.print 定义因为 Nashorn 不提供默认的全局 console对象和 Haskell 的 putStrLn否则似乎没有打印任何东西。

另一件事是需要使用 sysexit 退出 JVM。使用 java.lang.System.exit 实现的 FFI 函数.

我有两个问题:
  • 类似于 console.log ,在必须定义的 ghcjs 中假设了哪些其他主机依赖项?
  • JVM没有正常关闭是因为ghcjs在后台创建了事件循环还是其他原因?有什么办法可以避免这种情况并使程序正常退出?
  • 最佳答案

    luite 的帮助下,我终于可以使用 shims for the JVM :

  • 平台检测(shims/src/platform.js)

    Java 的 Nashorn 提供了全局 Java可用于检测我们是否在 JVM 下运行的变量。如果定义了这个变量,一个全局变量h$isJvm设置类似于 h$isNode对于 ghcjs 运行时。然后,此变量将用于在其他地方提供 JVM 特定代码。我们也可以定义console.log在这里,写入控制台可以在 JVM 上开箱即用,而无需在用户程序中定义它:
    if(typeof Java !== 'undefined') {
    h$isJvm = true;
    this.console = {
    log: function(s) {
    java.lang.System.out.print(s);
    }
    };
    }
  • 正常退出 JVM (shims/src/thread.js)

    GHCJS 有一个名为 h$exitProcess 的方法用于退出进程。使用我们在上一步中定义的变量 h$isJvm ,我们可以添加以下代码让JVM退出:
    if (h$isJvm) {
    java.lang.System.exit(code);
    }
  • 命令行参数 (shims/src/environment.js)

    Nashorn 提供全局 arguments包含传递给 jjs 的命令行参数值的变量.我们可以使用这个变量添加一个垫片:
    if(h$isJvm) {
    h$programArgs = h$getGlobal(this).arguments;
    }

  • 使用这些垫片,我们可以在 JVM 上运行大多数开箱即用的 Haskell。这是问题中的原始程序,在 GHCJS 中添加了上述垫片:
    module Main where

    main = putStrLn "Hello from Haskell!"

    这个常规的 Haskell 代码现在在 JVM 中开箱即用。甚至那些不平凡的小程序也直接在 JVM 上运行。例如,以下代码取自 here :
    {-# LANGUAGE DeriveGeneric     #-}
    {-# LANGUAGE OverloadedStrings #-}

    import Options.Generic

    data Example = Example { foo :: Int, bar :: Double }
    deriving (Generic, Show)

    instance ParseRecord Example

    main = do
    x <- getRecord "Test program"
    print (x :: Example)

    我们可以使用 stack 构建它并使用 jjs 运行传递命令行参数:
    haskell-jvm-hello$ stack build

    haskell-jvm-hello$ jjs ./.stack-work/dist/x86_64-linux/Cabal-1.22.4.0_ghcjs/build/haskell-jvm-hello-exe/haskell-jvm-hello-exe.jsexe/all.js -- --help
    Test program

    Usage: a.js --foo INT --bar DOUBLE

    Available options:
    -h,--help Show this help text

    haskell-jvm-hello$ jjs ./.stack-work/dist/x86_64-linux/Cabal-1.22.4.0_ghcjs/build/haskell-jvm-hello-exe/haskell-jvm-hello-exe.jsexe/all.js -- --foo 1 --bar 2.5
    Example {foo = 1, bar = 2.5}

    关于haskell - 在 JVM 上运行编译为 JavaScript 的 Haskell,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35715256/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com