如何从JavaScript调用单个Idris函数?

时间:2019-07-19 22:44:51

标签: javascript ffi idris

假设我在Idris中有一个函数可以进行一些计算。为简单起见,现在暂时字符串键入。

f: String -> String

如何将该函数编译为JavaScript,以便可以从任何普通的JavaScript代码中调用它?

如果这太容易了,那么假设f而不是String处理Double甚至是自定义的Idris数据类型。

我知道我可以使用Main.main函数编译整个模块,并且将输出或多或少难以理解的JavaScript。我可以手动从那里提取功能吗?我该怎么办?


建议。尽管我回答了自己,但我仍在寻找更好的解决方案,因此欢迎您。

2 个答案:

答案 0 :(得分:3)

使用this example,至少在Node后端看来这是可行的。我已将interact标记为export,并添加了一个lib ary描述符:

module Main

import Data.String

f: Double -> Double
f x = x + 1

export interact: String -> String
interact s = let x = parseDouble s in
    case x of
         Nothing => "NaN"
         Just x => show (f x)

main: IO ()
main = do
    s <- getLine
    putStrLn (interact s)

lib : FFI_Export FFI_JS "" []
lib = Data String "String" $
      Fun interact "interact" $
      Fun main "main" $
      End

然后我用--interface标志进行了编译(这失败了,--codegen javascript ...):

idris --codegen node --interface  --output ExportToJS.js ExportToJS.idr

,结果的.js文件的末尾是这个:

module.exports = {
interact: Main__interact,
main: Main__interact
};
}.call(this))

这应该允许您从Node进行require("./ExportToJavaScript.js").interact("42"),并且可能与浏览器等效。

答案 1 :(得分:1)

是的,您可以手动提取任何功能。

  1. 按如下所示构建模块:

    module Main
    
    import Data.String
    
    f: Double -> Double
    f x = x + 1
    
    interact: String -> String
    interact s = let x = parseDouble s in
        case x of
             Nothing => "NaN"
             Just x => show (f x)
    
    main: IO ()
    main = do
        s <- getLine
        putStrLn (interact s)
    
  2. 编译如下:

    % idris --codegen javascript --output Main.js Main.idr
    

    将创建一个名为Main.js的文件。就像您说的那样,将有几兆字节的或多或少难以理解的JavaScript代码。

  3. 手动编辑此文件,然后进行类似的编辑:

    --- Resistors.js
    +++ Resistors-default.js
    @@ -1,7 +1,5 @@
     "use strict";
    
    -(function(){
    -
     const $JSRTS = {
         throw: function (x) {
             throw x;
    @@ -36130,7 +36128,3 @@
             }
         }
     }
    -
    -
    -$_0_runMain();
    -}.call(this))
    
  4. 现在请注意,此JS文件中带有注释,并使用Idris名称标记了JS函数。例如,对应于我们的interact函数,将找到以下JS函数:

    // Main.interact
    
    function Main__interact($_0_arg){
        const $_1_in = Data__String__parseDouble($_0_arg);
    
        if(($_1_in.type === 1)) {
            const $cg$3 = Main__bestMatch_39_($_1_in.$1, Main__manyResistors_39_());
            let $cg$2 = null;
            $cg$2 = $cg$3.$1;
            return Prelude__Show__Main___64_Prelude__Show__Show_36_Schema_58__33_show_58_0($cg$2);
        } else {
            return "NaN";
        }
    }
    
  5. 如果将此JS文件作为脚本附加到网页,则可以在浏览器中打开JS控制台并与Idris函数进行交互,如下所示:

    Main__interact("10")
    "11"
    

希望这会有所帮助!