首先,为我的英语感到抱歉,而且我正在努力学习Haskell
我会从java运行Frege代码(Haskell)调用,对于几乎所有的方面,我设法使它按照在各个站点上找到的指令工作。但是我仍然有一个关于以下代码的问题,很抱歉请求的细节.
javaHelloTest.java
package local.java;
import java.io.PrintWriter;
import java.util.Arrays;
import frege.runtime.Runtime;
import frege.runtime.Runtime.*;
import frege.java.Util.TList;
import frege.prelude.PreludeArrays;
import frege.prelude.PreludeBase;
import frege.control.monad.State;
import frege.run7.*;
import local.frege.FregeHelloTest;
public class JavaHelloTest {
public static void main(String[] args) {
System.out.println("Hello World from Java code ... ");
System.out.println("========================");
System.out.println("callingMain0 ... ");
System.out.println("------------------------");
FregeHelloTest.callingMain0(Thunk.<PreludeBase.TList<String>>lazy(PreludeArrays.IListSource_JArray.<String>toList(args)));
System.out.println("========================");
System.out.println("callingMain1 ... ");
System.out.println("------------------------");
FregeHelloTest.callingMain1(Thunk. <PreludeBase.TList<String>>lazy(PreludeArrays.IListSource_JArray.<String>toList(args)));
System.out.println("========================");
System.out.println("callingMain2 ... ");
System.out.println("------------------------");
FregeHelloTest.callingMain2(Thunk. <PreludeBase.TList<String>>lazy(PreludeArrays.IListSource_JArray.<String>toList(args)));
System.out.println("========================");
}
}fregeHelloTest.fr
module local.frege.FregeHelloTest where
import Prelude.PreludeBase as PreludeBase
main :: [String] -> IO ()
main args = println $ "Hello World from Frege code ..."
callingMain0 :: [String] -> ()
callingMain0 ss = PreludeBase.ST.performUnsafe(main ss)
callingMain1 :: [String] -> IO ()
callingMain1 ss = return ( PreludeBase.ST.performUnsafe(main ss) )
callingMain2 :: [String] -> ()
callingMain2 ss = PreludeBase.ST.run( return ( PreludeBase.ST.performUnsafe(main ss) ) )fregeHelloTest.java (由fregec生成)
{ ... omissis ... }
final public class FregeHelloTest {
final public static Func.U<RealWorld, Short> $main(final Lazy<PreludeBase.TList<String/*<Character>*/>> arg$1) {
return PreludeBase.<Func.U<RealWorld, Short>, String/*<Character>*/>$(
new Func.U.D<String/*<Character>*/, Func.U<RealWorld, Short>>() {
public Lazy<Func.U<RealWorld, Short>> apply(final Lazy<String/*<Character>*/> η$7611) {
return Thunk.<Func.U<RealWorld, Short>>shared(
new Lazy.D<Func.U<RealWorld, Short>>() {
public Func.U<RealWorld, Short> call() {
return Prelude.<String/*<Character>*/>println(PreludeText.IShow_String.it, η$7611.call());
}
}
);
}
},
Thunk.<String/*<Character>*/>lazy("Hello World from Frege code ...")
).call();
}
final public static short callingMain2(final Lazy<PreludeBase.TList<String/*<Character>*/>> arg$1) {
return (short)PreludeBase.TST.<Short>run(
PreludeMonad.IMonad_ST.<Object, Short>pure(
Thunk.<Short>nested(
new Lazy.D<Lazy<Short>>() {
public Lazy<Short> call() {
return PreludeBase.TST.<Short>performUnsafe(FregeHelloTest.$main(arg$1));
}
}
)
)
).call();
}
final public static Func.U<RealWorld, Short> callingMain1(final Lazy<PreludeBase.TList<String/*<Character>*/>> arg$1) {
return PreludeMonad.IMonad_ST.<RealWorld, Short>pure(
Thunk.<Short>nested(
new Lazy.D<Lazy<Short>>() {
public Lazy<Short> call() {
return PreludeBase.TST.<Short>performUnsafe(FregeHelloTest.$main(arg$1));
}
}
)
);
}
final public static short callingMain0(final Lazy<PreludeBase.TList<String/*<Character>*/>> arg$1) {
return (short)PreludeBase.TST.<Short>performUnsafe(FregeHelloTest.$main(arg$1)).call();
}
public static void main(final java.lang.String[] argv) { ... omissis ... }
}程序输出。带有入口点: local.java.JavaHelloTtest.main
------------------
Hello World from Java code ...
========================
callingMain0 ...
------------------------
Hello World from Frege code ...
========================
callingMain1 ...
------------------------
========================
callingMain2 ...
------------------------
Hello World from Frege code ...
========================经过很长一段时间(对我来说)调查后,我意识到"CallingMain1“没有执行任何事情是正确的。事实上,正如您所看到的,由"callingMain2“生成的需要一个”运行“.但是如果我试图用"callingMain1“执行返回的”PreludeBase.TST.run“IDE (Eclipseandthe编译器),告诉我签名是不正确的,PreludeBase.TST.run是在"Object”上,而不是在"RealWorld“上,实际上,在" callingMain2”的情况下,编译器设置了一个"Object“,而不是一个"RealWorld”来运行callingMain2。
显然(我认为) "callingMain1“的签名(Haskell)是正确的。我觉得没人能碰..。
现在问题是..。在这一点上,我认为,也许,它应该是一个函数..。TST.runOnRealWorld允许从尚未“callingMain1”返回的IO ()进行评估;但是,正如生成"callingMain2“时,我清楚地看到操作在”对象“上的动态变化,我必须假定此函数不存在.
这是想要的,还是只需要添加一个允许java计算"callingMain1“输出的"run”方法?
或者,更可能的是,我对.提前谢谢..。
发布于 2017-03-21 17:43:39
首先,我想说,没有必要为试图学习Haskell而感到遗憾。恰恰相反。把自己看成是精英,insead!
为callingMain0生成的Java代码是从java运行I/O操作的正确方法。我建议直接使用它(或者通过Java实用程序方法),并且出于卫生的原因,不要像callingMain0那样拥有一个看似纯粹的助手函数。
顺便说一句,当您传递一个具有Frege代数数据类型(枚举除外)的值时,您不需要将它包装在额外的Thunk.<...>lazy()中,因为所有这些类型都已经实现了Lazy接口。所以你可以写:
FregeHelloTest.callingMain0(PreludeArrays.IListSource_JArray.<String>toList(args));不管函数实际需要的是一个惰性列表还是一个严格的列表,这都是可行的。
接下来,callingMain1,当然,它什么也不做,就像
FregeHelloTest.$main(...) 什么也做不了。为什么?因为类型是IO (),所以这种类型告诉我们,函数返回一个在执行该操作时将生成()的操作。在Frege中执行IO操作的唯一的方式是通过PreludeBase.TST.<T>performUnsafe。但是,您不会将操作(即调用callingMain1(...)的结果)传递给performUnsafe。因此,从来不执行该操作。
备注:当您检查为您的Frege模块生成的代码时,您可能已经注意到存在一个main方法。如果没有,去查一查。您将看到JVM输入的main方法只是通过将其结果传递给performUnsafe来调用$main (它对应于您的main函数)。没有别的办法了。
还有一点:有一个普遍存在的误解,即带有IO类型的Haskell (或Frege)函数是不纯的。你看,这完全是错误的。您可以任意频繁地调用IO函数,除了构造IO操作之外,不会发生任何事情。这绝对是纯的。对于相同的参数,您将得到“相同”(在行为方面,因为我们无法比较它们) IO操作,并且在实际执行之前不会出现副作用。
但是,您会问,为什么performUnsafe在callingMain1函数中什么也不做呢?这是因为return很懒。根本没有理由去评估它的论点。这还表明,performUnsafe在Frege代码中确实是不安全的,所有的赌注都不确定何时和按什么顺序进行评估。另一个例子是:
tail [IO.performUnsafe $ print "Ha"]最后,calingMain2 --这是最令人困惑的,我不知道你在想什么。ST.run将只运行幻影类型中多态的真正ST操作。现在,可以肯定的是,您创建了这样一个ST操作,方法是
return IO.performUnsafe(main args)ST.run运行了这个操作,从而对performUnsafe进行了评估。
但是不能将ST.run应用于IO操作。考虑一下
type IO = ST RealWorld
ST.run :: (forall s. ST s a) -> a当你说:
ST.run(print "foo")这是行不通的,因为RealWorld不像s那样多态。幸运的是,您也不能在Java中欺骗它,因为Func<RealWorld,Short>不是Func<Object,Short>的一个子类型。
最后,我想重新迭代:要从Java运行IO操作,除了将它传递给performUnsafe之外,没有别的办法了。
希望这有帮助,可以随意问一些还不清楚的事情。
https://stackoverflow.com/questions/42905977
复制相似问题