如何在Android上运行Frege程序?

时间:2013-06-20 19:39:28

标签: android haskell dalvik frege

我对使用函数式语言进行Android编程感兴趣,最好是接近Haskell。 Frege似乎是个不错的选择。我发现有人已经做过这样的proof-of-concept application,但我找不到它的来源或类似的东西。

所以我的问题是,如何在Android上运行Frege程序,它有多难以及最终会遇到什么障碍?

5 个答案:

答案 0 :(得分:6)

我看到的主要障碍是,目前无法将frege源编译为实现某个接口或扩展另一个类的java类。

相反,从frege模块生成的java类只是静态方法和您定义的其他东西的命名空间。

因此,要制作一个简单的Android项目,从frege调用java是不够的,这很容易,但也可以从java调用frege。换句话说,你需要字面意义上的完整* inter *可操作性。

当然,有可能这样做,但必须说代码生成并不是为了方便java使用而设计的。

我还没有完成Android项目,因此我不确定需要多少胶水代码。

最后一个警告:Gabriel Riba之前的工作是使用早期版本的编译器完成的。甚至还有支持JDK6的frege发行版的链接 - 请不要使用它,它与更新的版本不兼容。

如果你愿意接受它,你将通过上面提到的谷歌小组获得所有可能的支持。如果有人制作并记录了一些“规范”的方法来实现这一点,那就太棒了。

答案 1 :(得分:3)

我不熟悉frege,我没有尝试在Android上使用scala或其他JVM语言。

话虽如此,如果我尝试这样的话,这些是我可能会尝试找出如何使其发挥作用的步骤。

  1. 在frege中构建一个基于命令行的简单HelloWorld类型的应用程序,可以使用例如java -jar HelloWorld.jar HelloWorld

  2. 在HelloWorld.jar上运行dx,然后尝试使用dalvikvm从adb shell获取Android设备上的示例。即dalvikvm -cp blah.dex HelloWorld

  3. 弄清楚如何从frege中的Android sdk提供的android.jar中引用/使用类

  4. 在frege中构建一个简单的概念验证活动类,并从中手动构建一个classes.dex文件

  5. 在java中构建类似的概念验证应用程序,并使用现有的android工具构建apk

  6. 替换apk中的classes.dex,重新签名apk,看看它是否有效

  7. 如果你做得那么多,那么你可以从那里开始为frege创建一个更好的构建故事,使用aapt编译资源并最终从头开始构建一个完整的apk。

答案 2 :(得分:2)

从快速的网络搜索中我可以收集到的一切,包括来自frege - 编程语言邮件列表的一些点击,它看起来不像只有Frege的Android应用程序。

相反,您必须使用其他一些支持Android的语言并使用它来调用您的Frege代码。生成这样的“存根”可能会自动完成,但我没有看到现有的工具。

Frege和Android的Java编译器生成的Java代码也存在问题,但这似乎是使用逆向翻译工具相对容易解决的问题。

https://groups.google.com/forum/#!topic/frege-programming-language/Ounzmu-oHJQ https://groups.google.com/forum/#!topic/frege-programming-language/8bkWorojiiY

我还希望有一种参考多态性和ad-hoc多态性可用于Android开发的引用透明,强类型语言。虽然缺少这一点,但我建议使用Scala进行Android开发。

答案 3 :(得分:2)

如果你想在弗雷格完​​全编写你的应用程序,那将会更加棘手。您需要为Android API编写包装器,因为FregeAndroid wrapper似乎是missing some files

但是,如果你想用Java编写你的UI,并为你的应用程序逻辑调用Frege,我有一个sample project来说明如何做到这一点。

我的示例项目在Frege中有这个功能:

extraText :: String -> String
extraText who = "\nHello, " ++ who ++ "!"

然后我从Java调用:

public class FregeActivity extends Activity
{
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        TextView textView = (TextView) findViewById(R.id.txt);
        textView.append(FregeCode.extraText("Android"));
    }
}

看起来像这样

FregeActivity

我的示例项目使用了Frege 3.23,因此您可以使用old way of calling Frege from Java。我没有尝试使用过Frege 3.24,但是如果你想尝试一下,你可以使用the new way

唯一非常棘手的部分是获得构建Frege代码的build.gradle。我从弗雷格邮件列表上的snippet posted by Andreas Ländle开始,然后我将其充实到a complete build.gradle。我无法让Proguard工作,因此生成的APK包含整个frege.jar。这会使应用程序膨胀一点,并且需要打开Multidex,否则它似乎没问题。

另请注意,我的示例项目需要API Level 21或更高,因为Frege需要ForkJoinPool,Android只有21级以上。

答案 4 :(得分:1)

对于仍然感兴趣的人,我有一篇关于它的博客文章here。您必须设置gradle构建以将Frege代码编译为java并将其放入java源路径中。然后你必须子类化活动并定义一些自定义包装器

data Bundle = native android.os.Bundle

data Context = native android.content.Context

data FregeActivity = native android.app.Activity where
    native getApplicationContext :: MutableIO FregeActivity -> IO (MutableIO Context)
    native setContentView :: MutableIO FregeActivity -> MutableIO TextView -> IO ()

data TextView = native android.widget.TextView where
    native new :: MutableIO Context -> STMutable RealWorld TextView
    native setText :: MutableIO TextView -> String -> IO ()

onCreateF :: MutableIO FregeActivity -> IO ()
onCreateF !this = do
    context <- this.getApplicationContext
    tv <- TextView.new context
    tv.setText "Hello, Android - Love, Frege"
    this.setContentView tv

native module type FregeActivity where {
    @Override
    public void onCreate(android.os.Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final frege.run7.Func.U<Object,Short> res = RunTM.<frege.run7.Func.U<Object,Short>>cast(onCreateF(this)).call();
        frege.prelude.PreludeBase.TST.run(res).call();
    }
}