gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 06:58:19 24 4
gpt4 key购买 nike

我的 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)

然后我想从 Java 中定义以下函数(其中 DATABASE 是一个字符串常量):

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

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

通过实验,我不得不将代码更改为

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

我将 null 放在后者 apply 中只是为了表明我传入的内容无关紧要。我不知道为什么我必须应用该函数三次(我不能立即强制求值)。有什么办法可以删除应用程序或对为什么需要它们进行一些合理化?(注意:使用 .result() 对这种情况没有帮助。)

最佳答案

这样做的原因是,在此实现中,ST 操作表示为“函数对象”,其中实现伴随函数的方法忽略它的参数。

记忆一下ST的定义可能有助于理解:

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

首先要注意的是 data 实际上会在 Haskell 中写成 newtype。所以ST只是一种类型重命名,即一个ST Action 实际上是一个函数。

但是,abstract 确保您无法查看 ST 数据构造函数,因此无法直接从 Frege 代码运行函数。

这解释了为什么在 Java 中,在将参数应用于返回 ST 操作的函数之后,需要将该额外参数应用于结果,正如我们所见,只不过是另一个功能。

那么,为什么要在代码中执行两次呢?因为 IO 是(从我的头顶):

type IO = ST RealWorld

STMutable

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

所以问题出在你的 getDatabase 函数上,它返回一个 IO Action ,当执行时,返回一个 ST Action ,当执行时,返回一个可变的数组列表。

这可能不是您想要的。我猜你在 getDatabase 的最后一行上纠结了一段时间,它应该是:

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

当时的返回类型

IO (Mutable RealWorld ArraList)

或者只是

IOMutable ArrayList

另外一点:你不需要重新引入split,它已经存在了。您可以编写将分号分隔的输入行分开的行:

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

另见 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

加法

Dierks 的回答提出了一个有趣的观点,即我们应该有一个实用函数来从 Java 代码运行 ST(或 IO)操作。事实上,有这样一个函数,它的名字是ST.performUnsafe(在Frege中),在Haskell中被称为unsafePerformIO

事实上,使用这个函数可以使 Java 代码更健壮以应对实现中的变化,因此强烈建议代替此处使用的 .apply(null) 代码。

关于java - 从 Java 调用 Frege 与参数数量不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32806894/

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