我对用函数式语言为 Android 编程很感兴趣,最好是接近 Haskell。弗雷格似乎是一个不错的选择。我发现有人已经做过这样的概念验证应用程序,但我找不到它的来源或类似的东西。
所以我的问题是,如何在 Android 上运行 Frege 程序,它有多难,最终的障碍是什么?
我看到的主要障碍是,目前无法将 frege 源代码编译为实现某个接口或扩展另一个类的 java 类。
相反,从 frege 模块生成的 java 类只是静态方法和您定义的其他内容的命名空间。
因此,要制作一个非常简单的Android项目,仅仅从frege调用java是不够的,这很容易,而且还从java调用frege。换句话说,从字面上看,您需要完全的*互*操作性。
当然可以,但必须说代码生成并不是为了方便从 java 中使用而设计的。
我还没有完成一个 Android 项目,因此我不确定需要多少胶水代码。
最后一个警告:Gabriel Riba 之前的工作是使用早期版本的编译器完成的。甚至还有一个指向支持 JDK6 的 frege 发行版的链接——请不要使用那个,它与更新的版本不兼容。
如果您仍然愿意接受它,您将通过上述 google 小组获得一切可能的支持。如果有人制作并记录了一些“规范”的方式来实现这一点,那就太好了。
我对 frege 不熟悉,也没有尝试在 Android 上使用 scala 或其他 JVM 语言。
话虽如此,如果我要尝试这样的事情,我可能会采取这些步骤来尝试弄清楚如何让它发挥作用。
在 frege 中构建一个简单的基于命令行的 HelloWorld 类型应用程序,可以运行,例如 java -jar HelloWorld.jar HelloWorld
在 HelloWorld.jar 上运行 dx,然后尝试使用 dalvikvm 从 adb shell 让示例在 android 设备上运行。即dalvikvm -cp blah.dex HelloWorld
弄清楚如何从 frege 中的 Android sdk 提供的 android.jar 中引用/使用类
在 frege 中构建一个简单的概念证明 Activity 类,并从中手动构建一个 classes.dex 文件
在java中构建一个类似的概念证明应用程序并使用现有的android工具来构建一个apk
替换apk中的classes.dex,退出apk,看看是否有效
如果你做了这么多工作,那么从那里,你可以为 frege 编写一个更好的构建故事,使用 aapt 编译资源并最终“从头开始”构建一个完整的 apk。
如果你想完全用 Frege 编写你的应用程序,那将更加棘手。您需要为 Android API 编写包装器,因为FregeAndroid 包装器似乎缺少一些文件。
但是,如果你想用 Java 编写你的 UI,并调用 Frege 来实现你的应用程序逻辑,我有一个示例项目来展示如何做到这一点。
我的示例项目在 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"));
}
}
看起来像这样
我的示例项目使用 Frege 3.23,因此您将使用从 Java 调用 Frege 的旧方法。我没有尝试过使用 Frege 3.24,但如果你想尝试,你会使用新的方式。
唯一真正棘手的部分是获得一个build.gradle
可以构建 Frege 代码的代码。我从Andreas Ländle在 Frege 邮件列表上发布的一个片段开始,然后我将其充实为一个完整的 build.gradle。我无法让 Proguard 工作,因此生成的 APK 包含整个frege.jar
. 这使应用程序有点膨胀,它需要打开Multidex,但除此之外它似乎没问题。
另外,请注意,我的示例项目需要API 级别 21或更高级别,因为 Frege 需要ForkJoinPool,而 Android 仅在级别 21 及更高级别中具有此功能。
从我可以从快速网络搜索中收集到的所有内容,包括来自 frege-programming-language 邮件列表的一些点击,它看起来不像是仅 Frege 的 Android 应用程序是可能的。
相反,您必须采用其他支持 Android 的语言并使用它来调用您的 Frege 代码。生成这样的“存根”可能会自动完成,但我没有看到这样做的现有工具。
Frege 生成的 Java 代码和 Android 的 Java 编译器也存在一些问题,但这似乎是使用逆向翻译工具相对容易解决的问题。
https://groups.google.com/forum/#!topic/frege-programming-language/Ounzmu-oHJQ https://groups.google.com/forum/#!topic/frege-programming-language/8bkWorojiiY
我还希望有一种引用透明、强类型的语言,它同时具有参数多态性和临时多态性,可用于进行 Android 开发。虽然缺少这一点,但我推荐使用 Scala 进行 Android 开发。
对于仍然感兴趣的人,我在这里有一篇关于它的博客文章。您必须设置您的 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();
}
}