简体   繁体   English

从Java调用Frege与参数数量不匹配

[英]Calling Frege From Java Doesn't Match Number of Parameters

I have Frege code as follows (mostly, just pay attention to the type signature for getDatabase) 我有以下Frege代码(大多数情况下,只需注意getDatabase的类型签名)

module fregeHelper.FregeCode where 

--Java's String.split method
pure native split :: String -> String -> JArray String

--Java's ArrayList<t>
data ArrayList t =native java.util.ArrayList where
    native new :: () -> STMutable s (ArrayList t)
    native add::Mutable s (ArrayList t)-> t -> ST s ()

getDatabase::String->(IO (STMutable s (ArrayList (String, String))))
getDatabase s = do
        fileContents <- readFile s
        let processedData = map ((\x->(elemAt x 0, elemAt x 1)) . (flip split ";")) . lines $ fileContents
        return $ fold foldAdd (ArrayList.new ()) processedData
    where
        foldAdd::ST s (Mutable s (ArrayList t)) -> t -> ST s (Mutable s (ArrayList t))
        foldAdd list elem = list >>= \x->(ArrayList.add x elem >> return x)

Then from Java I want to define the following function thusly (where DATABASE is a string constant): 然后,我想从Java中定义以下函数(其中DATABASE是字符串常量):

private void readDatabase() {
    myList = Delayed.<ArrayList<TTuple2>>forced(
            fregeHelper.FregeCode.getDatabase(DATABASE));
}

However, this gives me a java.lang.ClassCastException: frege.prelude.PreludeBase$TST$1 cannot be cast to java.util.ArrayList 但是,这给了我一个java.lang.ClassCastException: frege.prelude.PreludeBase$TST$1 cannot be cast to java.util.ArrayList

Through experimentation, I had to change the code to be 通过实验,我不得不将代码更改为

private void readDatabase() {
    fighters = Delayed.<ArrayList<TTuple2>>forced(
            fregeHelper.FregeCode.getDatabase(DATABASE)
            .apply(null)
            .apply(null)
            );
}

I've put null in the latter applies just to show that it doesn't matter what I pass in. I have no idea why I have to apply the function three times (I can't just immediately force evaluation). 我在后者中使用null只是为了表明我传入的内容无关紧要。我不知道为什么必须重复应用该函数三次(我不能立即强制求值)。 Is there any way I can either remove the applies or have some rationalization as to why they're necessary? 我有什么办法可以删除应用程序,也可以对为什么有必要进行合理化处理? (Note: using .result() doesn't help the case.) (注意:使用.result()不能解决问题。)

The reason for this is that in this implementation, a ST action is represented as a "function object", where the method that implements the accompagnied function ignores it argument. 这样做的原因是,在此实现中,ST动作表示为“功能对象”,在其中实现已实现功能的方法忽略了它的参数。

It may help the understanding to recall the definition of ST: 回顾一下ST的定义可能有助于理解:

abstract data ST s a = ST (s -> a) where ...

First thing to note is that the data would actually be written newtype in Haskell. 首先要注意的是,该data实际上被写入newtype在Haskell。 So ST is just a type renaming, that is, an ST action is actually a function. 因此, ST只是类型重命名,也就是说,ST动作实际上是一个函数。

However, the abstract makes sure you cannot look through the ST data constructor and hence cannot run the function directly from Frege code. 但是, abstract确保您无法浏览ST数据构造函数,因此不能直接从Frege代码运行该函数。

This explains why, from Java, after applying the arguments to a function that returns a ST action, one needs to apply that extra argument to the result, which is, as we've seen, nothing but another function. 这解释了为什么从Java将参数应用到返回ST动作的函数后,需要将多余的参数应用于结果的原因,正如我们所看到的,该参数仅是另一个函数。

So, why then, do you have to do this two times in your code? 那么,为什么然后必须在代码中执行两次呢? Because IO is (from the top of my head): 因为IO是(从我的头开始):

type IO = ST RealWorld

and STMutable is STMutable

type STMutable s x = ST s (Mutable s x)

So the problem lies in your getDatabase function, which returns an IO action, which, when executed, returns an ST action, which, when executed, returns a mutable ArrayList. 因此,问题出在getDatabase函数上,该函数返回IO动作,执行时返回ST动作,执行时返回可变的ArrayList。

This is probably not what you wanted. 这可能不是您想要的。 And I guess you struggled a while with the last line in getDatabase , which should probably read: 而且我猜想您在getDatabase的最后一行getDatabase挣扎,该行可能显示为:

list <- ArrayList.new ()
foldM (\xs\x -> ArrayList.add xs x >> return xs) list processedData 

the return type being then 然后返回类型

IO (Mutable RealWorld ArraList)

or just 要不就

IOMutable ArrayList

Another point besides: you should not need to re-introduce split , it is already there. 除此以外的另一点是:您不需要重新引入split ,它已经存在。 You could write that line that takes the semicolon delimitted input lines apart: 您可以编写以分号分隔的输入行分开的行:

[ (a,b) | line <- lines fileContent, [a,b] <- ´;´.splitted line ]

See also http://www.frege-lang.org/doc/frege/java/util/Regex.html#Regex.splitted and http://www.frege-lang.org/doc/frege/java/util/Regex.html#Regex.split 另请参见http://www.frege-lang.org/doc/frege/java/util/Regex.html#Regex.splittedhttp://www.frege-lang.org/doc/frege/java/util/ Regex.html#Regex.split

Addition 加成

Dierks answer makes an interesting point that we should have an utility function for running ST (or IO) actions from Java code. Dierks的回答提出了一个有趣的观点,我们应该具有一个实用程序函数,用于从Java代码运行ST(或IO)操作。 In fact, there is such a function, its name is ST.performUnsafe (in Frege) and it is known in Haskell as unsafePerformIO . 实际上,有一个这样的函数,其名称为ST.performUnsafe (在Frege中),在Haskell中称为unsafePerformIO

In fact, using this function would make Java code more robust against changes in the implementation and is therefore strongly recommended in place of the .apply(null) code used here. 实际上,使用此功能将使Java代码对实现的更改更健壮,因此强烈建议代替此处使用的.apply(null)代码。

I am sure that others can provide better answers but the reason for what looks like extra parameters that you have to pass when forcing evaluation of the Delayed are the IO and STMutable types. 我确信其他人可以提供更好的答案,但是在强制评估Delayed时必须传递的额外参数的原因是IO和STMutable类型。

I came across the same issue here: https://github.com/Frege/FregeFX/blob/f2f548071afd32a08e9b24f6fb6bbece74d4213b/fregefx/src/main/java/org/frege/FregeFX.java#L19-L19 我在这里遇到了相同的问题: https : //github.com/Frege/FregeFX/blob/f2f548071afd32a08e9b24f6fb6bbece74d4213b/fregefx/src/main/java/org/frege/FregeFX.java#L19-L19

It may be worth considering a utility method "deeplyForced" (?) that shields the Java developer from these details. 可能值得考虑使用实用程序方法“ deeplyForced”(?),该方法可以使Java开发人员免受这些细节的影响。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM