我对使用函数式语言进行Android编程感兴趣,最好是接近Haskell。 Frege似乎是个不错的选择。我发现有人已经做过这样的proof-of-concept application,但我找不到它的来源或类似的东西。
所以我的问题是,如何在Android上运行Frege程序,它有多难以及最终会遇到什么障碍?
答案 0 :(得分:6)
我看到的主要障碍是,目前无法将frege源编译为实现某个接口或扩展另一个类的java类。
相反,从frege模块生成的java类只是静态方法和您定义的其他东西的命名空间。
因此,要制作一个简单的Android项目,从frege调用java是不够的,这很容易,但也可以从java调用frege。换句话说,你需要字面意义上的完整* inter *可操作性。
当然,有可能这样做,但必须说代码生成并不是为了方便java使用而设计的。
我还没有完成Android项目,因此我不确定需要多少胶水代码。
最后一个警告:Gabriel Riba之前的工作是使用早期版本的编译器完成的。甚至还有支持JDK6的frege发行版的链接 - 请不要使用它,它与更新的版本不兼容。
如果你愿意接受它,你将通过上面提到的谷歌小组获得所有可能的支持。如果有人制作并记录了一些“规范”的方法来实现这一点,那就太棒了。
答案 1 :(得分:3)
我不熟悉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中构建一个简单的概念验证活动类,并从中手动构建一个classes.dex文件
在java中构建类似的概念验证应用程序,并使用现有的android工具构建apk
替换apk中的classes.dex,重新签名apk,看看它是否有效
如果你做得那么多,那么你可以从那里开始为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"));
}
}
看起来像这样
我的示例项目使用了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();
}
}