如何从java评估/运行frege IO()monad?

时间:2017-03-20 14:17:35

标签: frege

首先抱歉我的英语,以及我试图学习Haskell的事实

我会从java运行Frege代码(Haskell),几乎所有 方面我设法使所有工作按照指示找到 在各种网站上...但我仍然有一个关于以下代码的问题, 对于请求的冗长感到抱歉...

javaHelloTest.java

$xml = [xml]'
<Events>
<Event Definition="Validate" DLLPath="" DLLName="Helper.dll" DLLClass="HelpMain" DLLRoutine="pgFeatureInfoOnValidate_WriteToRegSelectedFeatures" InputParameters="pTreeViewFeatureTreeServerOS" RunOnce="no"/>
<Event Definition="Validate1" DLLPath="" DLLName="Helper.dll1" DLLClass="HelpMain1" DLLRoutine="pgFeatureInfoOnValidate_WriteToRegSelectedFeatures" InputParameters="pTreeViewFeatureTreeServerOS" RunOnce="no"/>
</Events>
'

Select-XML -xml $xml -xpath "//Event/@DllName"

fregeHelloTest.fr

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.java(由fregec生成)

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

程序输出...带入口点:local.java.JavaHelloTtest.main

{ ... 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 ... }

}
经过不久(对我来说)的调查,我意识到这是正确的 &#34; CallingMain1&#34;没有执行任何事情......事实上,正如你所看到的那样 由&#34; callingMain2&#34;生成需要一个&#34;运行&#34; ......但如果我试试 使用&#34; run&#34;执行,返回&#34; callingMain1&#34; IDE (Eclipse然后编译器)告诉我签名不正确, PreludeBase.TST。&lt; Short&gt; run is on&#34; Object&#34;而不是&#34; RealWorld&#34;, 实际上,编译器在&#34; callingMain2&#34;设置一个 &#34;对象&#34;而不是&#34; RealWorld&#34;运行callingMain2。

显然(我认为)&#34; callingMain1&#34;的签名(Haskell)是正确的 ... 我认为没有人能碰到......

现在问题......在这一点上,我认为,也许应该如此 一个功能... TST.runOnRealWorld允许评估 IO()从尚未返回&#34; callingMain1&#34 ;;然而,就像在这一代 &#34; callingMain2&#34;我清楚地看到操作已经改变 即时#34;对象&#34;我必须假设这个功能不存在......

这是需要的,或者只是需要添加&#34;运行&#34;方法 允许java评估&#34; callingMain1&#34;的输出。 ?

或者,更可能的是,我很少理解......非常感谢...

1 个答案:

答案 0 :(得分:1)

首先,我想说没有必要为学习Haskell而感到遗憾。与此相反的。认为自己属于精英,内裤!

callingMain0生成的java代码是从Java运行I / O操作的正确代码。我建议直接使用它(或通过Java实用程序方法),并且出于卫生原因,没有看似纯粹的辅助函数,如callingMain0

顺便说一下,当你传递一个具有弗雷格代数数据类型的值(枚举除外)时,你不需要将它包装在额外的Thunk.<...>lazy()中,因为所有这些类型都已经实现了{ {1}}界面。所以你可以写:

Lazy

无论函数是否实际需要惰性列表或严格列表,都可以使用。

接下来,FregeHelloTest.callingMain0(PreludeArrays.IListSource_JArray.<String>toList(args)); 当然,它什么都不做,就像

一样
callingMain1

什么都不做。为什么?因为类型是FregeHelloTest.$main(...) 此类型告诉我们该函数返回一个操作,该操作在执行该操作时将产生IO ()。在弗雷格执行IO操作的唯一方式是()。但是,您不会将操作(即调用PreludeBase.TST.<T>performUnsafe的结果)传递给callingMain1(...)。因此,行动永远不会被执行。

备注:当您检查为Frege模块生成的代码时,您可能已经注意到存在performUnsafe方法。如果没有,请查阅。您将看到JVM输入的main方法只是通过将结果传递给main来调用$main(对应于您的Frege main函数) 。没有其他办法。

还有一句话:存在一个广泛存在的误解,即具有performUnsafe类型的Haskell(或Frege)函数是不纯的。你在这里看到这是完全错误的。您可以根据需要随时调用IO函数,除了构造IO操作外,什么都不会发生。这绝对是纯粹的。对于相同的论点,你将获得相同的&#34;相同的&#34; (在行为方面,因为我们可以比较它们)IO行动回来,并且不会发生副作用直到实际执行此类行为。

但是,你会问,为什么IO函数中的performUnsafe什么都不做?这是因为callingMain1是懒惰的。根本没有理由评估它的论点。这也表明return在弗雷格代码中确实是不安全的,并且关于何时以及将以何种顺序评估所有赌注都是关闭的。再举一个例子,试试:

performUnsafe

最后,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那样具有多态性。 幸运的是,你也不能用Java作弊,因为s不是Func<RealWorld,Short>的子类型

最后,我想重新迭代:要从Java运行IO操作,除了将其传递给Func<Object,Short>

之外别无他法。

希望这有帮助,随时可以询问尚不清楚的事情。