我找到了这个图书馆:https://hackage.haskell.org/package/java-bridge
根据作者的说法,支持Haskell对Java的3级绑定。正如所宣传的那样,mid level interface效果很好。但是,正如我正在使用它时,编写粘合代码开始变得重复和无聊,因为它只是以特定方式匹配类,方法和类型名称。 Here are some examples of using the mid level interface
据我了解,high level interface应该通过自动编写粘合代码来工作。 所以我试图让这项工作取得很大成功:
import Foreign.Java
import Foreign.Java.Bindings
import Data.Map as Map
main = runJava $ do
jClasses <- reflectJavaClasses ["java.sql.DriverManager"]
let info = Map.fromList [("java.sql.DriverManager", jClasses !! 0)]
io $ putStrLn $ printJavaClassModule (jClasses !! 0) "DriverManager" info
io $ putStrLn $ printJavaPackageModule "DriverManager" "DriverManager" info jClasses
io $ putStrLn $ printJavaClassBootfile (jClasses !! 0) "DriverManager" info
其中输出以下内容:
Preprocessing executable 'exp-java' for exp-java-0.1.0.0...
[1 of 1] Compiling Main ( main.hs, dist/build/exp-java/exp-java-tmp/Main.o )
Linking dist/build/exp-java/exp-java ...
{-# LANGUAGE Haskell2010 #-}
-- | Class @java.sql.DriverManager@
module DriverManager (
-- * Methods
deregisterDriver,
equals,
getClass,
getConnection,
getConnection',
getConnection'',
getDriver,
getDrivers,
getLogStream,
getLogWriter,
getLoginTimeout,
hashCode,
notify,
notifyAll,
println,
registerDriver,
setLogStream,
setLogWriter,
setLoginTimeout,
toString,
wait,
wait',
wait'',
-- * Information about this class.
info'
) where
import qualified Foreign.Java as JNI
import Foreign.Java ((-->))
import qualified Prelude as Prelude
import Prelude ((.), ($), (>>=), (>>), return)
import qualified Foreign.Java.Bindings.Support as JNIS
import Data.Functor ((<$>))
exp-java: classModImports in Foreign.Java.Bindings.Java2Haskell - class definition not found
任何可能导致此问题的想法请参阅下面的编辑。似乎需要使用classModImports in Foreign.Java.Bindings.Java2Haskell - class definition not found
?findJavaClasses
来解决此错误。
我使用的方式与预期不同吗?
我可以查看高级API的预期和工作用法示例吗?
有没有其他方法(例如不同的库)我可以(也/更容易)实现从Haskell到Java的易于使用的接口?
我设法得到了进一步的发展,但还没有完全发挥作用:
import Foreign.Java
import Foreign.Java.Bindings
import Data.Map as Map
main = runJava $ do
let target = "java.sql.DriverManager"
deps <- findJavaClasses 21 [target]
jClasses <- reflectJavaClasses deps
let jClassesMap = Map.fromList $ zip deps jClasses
let l = flip Map.lookup
let (Just targetJClass) = jClassesMap `l` target
io $ putStrLn $ printJavaClassModule targetJClass "DriverManager" jClassesMap
哪个输出:
{-# LANGUAGE Haskell2010 #-}
-- | Class @java.sql.DriverManager@
module DriverManager (
-- * Methods
deregisterDriver,
equals,
getClass,
getConnection,
getConnection',
getConnection'',
getDriver,
getDrivers,
getLogStream,
getLogWriter,
getLoginTimeout,
hashCode,
notify,
notifyAll,
println,
registerDriver,
setLogStream,
setLogWriter,
setLoginTimeout,
toString,
wait,
wait',
wait'',
-- * Information about this class.
info'
) where
import qualified Foreign.Java as JNI
import Foreign.Java ((-->))
import qualified Prelude as Prelude
import Prelude ((.), ($), (>>=), (>>), return)
import qualified Foreign.Java.Bindings.Support as JNIS
import Data.Functor ((<$>))
import qualified
info' = "DriverManager"
-- | @static synchronized deregisterDriver(java.sql.Driver) -> void@
deregisterDriver :: ( v1, JNIS.VoidResult void) => v1 -> JNI.Java void
deregisterDriver a1 = do
(Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
(Prelude.Just method) <- clazz `JNI.getStaticMethod` "deregisterDriver" JNI.::= JNI.object "java.sql.Driver" --> JNI.void
a1' <- Prelude.Just <$> JNI.asObject a1
result <- JNI.callStaticMethodE method a1'
JNIS.toVoidResult result
-- | @virtual equals(java.lang.Object) -> boolean@
equals :: (JNIS.BooleanResult boolean, this, v1) => this -> v1 -> JNI.Java boolean
equals this a1 = do
(Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
(Prelude.Just method) <- clazz `JNI.getMethod` "equals" JNI.::= JNI.object "java.lang.Object" --> JNI.boolean
this' <- JNI.asObject this
a1' <- Prelude.Just <$> JNI.asObject a1
result <- JNI.callMethodE method this' a1'
JNIS.toBooleanResult result
-- | @virtual native final getClass() -> java.lang.Class@
getClass :: ( this, JNIS.ObjectResult (object (' v2))) => this -> JNI.Java (object (' v2))
getClass this = do
(Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
(Prelude.Just method) <- clazz `JNI.getMethod` "getClass" JNI.::= JNI.object "java.lang.Class"
this' <- JNI.asObject this
result <- JNI.callMethodE method this'
JNIS.toObjectResult result
-- | @static getConnection(java.lang.String, java.lang.String, java.lang.String) -> java.sql.Connection@
getConnection :: ( v1, v2, v3, JNIS.ObjectResult (object ')) => v1 -> v2 -> v3 -> JNI.Java (object ')
getConnection a1 a2 a3 = do
(Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
(Prelude.Just method) <- clazz `JNI.getStaticMethod` "getConnection" JNI.::= JNI.object "java.lang.String" --> JNI.object "java.lang.String" --> JNI.object "java.lang.String" --> JNI.object "java.sql.Connection"
a1' <- Prelude.Just <$> JNI.asObject a1
a2' <- Prelude.Just <$> JNI.asObject a2
a3' <- Prelude.Just <$> JNI.asObject a3
result <- JNI.callStaticMethodE method a1' a2' a3'
JNIS.toObjectResult result
-- | @static getConnection(java.lang.String, java.util.Properties) -> java.sql.Connection@
getConnection' :: ( v1, v2, JNIS.ObjectResult (object ')) => v1 -> v2 -> JNI.Java (object ')
getConnection' a1 a2 = do
(Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
(Prelude.Just method) <- clazz `JNI.getStaticMethod` "getConnection" JNI.::= JNI.object "java.lang.String" --> JNI.object "java.util.Properties" --> JNI.object "java.sql.Connection"
a1' <- Prelude.Just <$> JNI.asObject a1
a2' <- Prelude.Just <$> JNI.asObject a2
result <- JNI.callStaticMethodE method a1' a2'
JNIS.toObjectResult result
-- | @static getConnection(java.lang.String) -> java.sql.Connection@
getConnection'' :: ( v1, JNIS.ObjectResult (object ')) => v1 -> JNI.Java (object ')
getConnection'' a1 = do
(Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
(Prelude.Just method) <- clazz `JNI.getStaticMethod` "getConnection" JNI.::= JNI.object "java.lang.String" --> JNI.object "java.sql.Connection"
a1' <- Prelude.Just <$> JNI.asObject a1
result <- JNI.callStaticMethodE method a1'
JNIS.toObjectResult result
-- | @static getDriver(java.lang.String) -> java.sql.Driver@
getDriver :: ( v1, JNIS.ObjectResult (object ')) => v1 -> JNI.Java (object ')
getDriver a1 = do
(Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
(Prelude.Just method) <- clazz `JNI.getStaticMethod` "getDriver" JNI.::= JNI.object "java.lang.String" --> JNI.object "java.sql.Driver"
a1' <- Prelude.Just <$> JNI.asObject a1
result <- JNI.callStaticMethodE method a1'
JNIS.toObjectResult result
-- | @static getDrivers() -> java.util.Enumeration@
getDrivers :: (JNIS.ObjectResult (object (' v2))) => JNI.Java (object (' v2))
getDrivers = do
(Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
(Prelude.Just method) <- clazz `JNI.getStaticMethod` "getDrivers" JNI.::= JNI.object "java.util.Enumeration"
result <- JNI.callStaticMethodE method
JNIS.toObjectResult result
-- | @static getLogStream() -> java.io.PrintStream@
getLogStream :: (JNIS.ObjectResult (object ')) => JNI.Java (object ')
getLogStream = do
(Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
(Prelude.Just method) <- clazz `JNI.getStaticMethod` "getLogStream" JNI.::= JNI.object "java.io.PrintStream"
result <- JNI.callStaticMethodE method
JNIS.toObjectResult result
-- | @static getLogWriter() -> java.io.PrintWriter@
getLogWriter :: (JNIS.ObjectResult (object ')) => JNI.Java (object ')
getLogWriter = do
(Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
(Prelude.Just method) <- clazz `JNI.getStaticMethod` "getLogWriter" JNI.::= JNI.object "java.io.PrintWriter"
result <- JNI.callStaticMethodE method
JNIS.toObjectResult result
-- | @static getLoginTimeout() -> int@
getLoginTimeout :: (JNIS.IntResult int) => JNI.Java int
getLoginTimeout = do
(Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
(Prelude.Just method) <- clazz `JNI.getStaticMethod` "getLoginTimeout" JNI.::= JNI.int
result <- JNI.callStaticMethodE method
JNIS.toIntResult result
-- | @virtual native hashCode() -> int@
hashCode :: (JNIS.IntResult int, this) => this -> JNI.Java int
hashCode this = do
(Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
(Prelude.Just method) <- clazz `JNI.getMethod` "hashCode" JNI.::= JNI.int
this' <- JNI.asObject this
result <- JNI.callMethodE method this'
JNIS.toIntResult result
-- | @virtual native final notify() -> void@
notify :: ( this, JNIS.VoidResult void) => this -> JNI.Java void
notify this = do
(Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
(Prelude.Just method) <- clazz `JNI.getMethod` "notify" JNI.::= JNI.void
this' <- JNI.asObject this
result <- JNI.callMethodE method this'
JNIS.toVoidResult result
-- | @virtual native final notifyAll() -> void@
notifyAll :: ( this, JNIS.VoidResult void) => this -> JNI.Java void
notifyAll this = do
(Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
(Prelude.Just method) <- clazz `JNI.getMethod` "notifyAll" JNI.::= JNI.void
this' <- JNI.asObject this
result <- JNI.callMethodE method this'
JNIS.toVoidResult result
-- | @static println(java.lang.String) -> void@
println :: ( v1, JNIS.VoidResult void) => v1 -> JNI.Java void
println a1 = do
(Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
(Prelude.Just method) <- clazz `JNI.getStaticMethod` "println" JNI.::= JNI.object "java.lang.String" --> JNI.void
a1' <- Prelude.Just <$> JNI.asObject a1
result <- JNI.callStaticMethodE method a1'
JNIS.toVoidResult result
-- | @static synchronized registerDriver(java.sql.Driver) -> void@
registerDriver :: ( v1, JNIS.VoidResult void) => v1 -> JNI.Java void
registerDriver a1 = do
(Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
(Prelude.Just method) <- clazz `JNI.getStaticMethod` "registerDriver" JNI.::= JNI.object "java.sql.Driver" --> JNI.void
a1' <- Prelude.Just <$> JNI.asObject a1
result <- JNI.callStaticMethodE method a1'
JNIS.toVoidResult result
-- | @static setLogStream(java.io.PrintStream) -> void@
setLogStream :: ( v1, JNIS.VoidResult void) => v1 -> JNI.Java void
setLogStream a1 = do
(Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
(Prelude.Just method) <- clazz `JNI.getStaticMethod` "setLogStream" JNI.::= JNI.object "java.io.PrintStream" --> JNI.void
a1' <- Prelude.Just <$> JNI.asObject a1
result <- JNI.callStaticMethodE method a1'
JNIS.toVoidResult result
-- | @static setLogWriter(java.io.PrintWriter) -> void@
setLogWriter :: ( v1, JNIS.VoidResult void) => v1 -> JNI.Java void
setLogWriter a1 = do
(Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
(Prelude.Just method) <- clazz `JNI.getStaticMethod` "setLogWriter" JNI.::= JNI.object "java.io.PrintWriter" --> JNI.void
a1' <- Prelude.Just <$> JNI.asObject a1
result <- JNI.callStaticMethodE method a1'
JNIS.toVoidResult result
-- | @static setLoginTimeout(int) -> void@
setLoginTimeout :: (JNIS.JInt v1, JNIS.VoidResult void) => v1 -> JNI.Java void
setLoginTimeout a1 = do
(Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
(Prelude.Just method) <- clazz `JNI.getStaticMethod` "setLoginTimeout" JNI.::= JNI.int --> JNI.void
a1' <- JNIS.toInt a1
result <- JNI.callStaticMethodE method a1'
JNIS.toVoidResult result
-- | @virtual toString() -> java.lang.String@
toString :: ( this, JNIS.ObjectResult (object ')) => this -> JNI.Java (object ')
toString this = do
(Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
(Prelude.Just method) <- clazz `JNI.getMethod` "toString" JNI.::= JNI.object "java.lang.String"
this' <- JNI.asObject this
result <- JNI.callMethodE method this'
JNIS.toObjectResult result
-- | @virtual final wait(long, int) -> void@
wait :: ( this, JNIS.JLong v1, JNIS.JInt v2, JNIS.VoidResult void) => this -> v1 -> v2 -> JNI.Java void
wait this a1 a2 = do
(Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
(Prelude.Just method) <- clazz `JNI.getMethod` "wait" JNI.::= JNI.long --> JNI.int --> JNI.void
this' <- JNI.asObject this
a1' <- JNIS.toLong a1
a2' <- JNIS.toInt a2
result <- JNI.callMethodE method this' a1' a2'
JNIS.toVoidResult result
-- | @virtual native final wait(long) -> void@
wait' :: ( this, JNIS.JLong v1, JNIS.VoidResult void) => this -> v1 -> JNI.Java void
wait' this a1 = do
(Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
(Prelude.Just method) <- clazz `JNI.getMethod` "wait" JNI.::= JNI.long --> JNI.void
this' <- JNI.asObject this
a1' <- JNIS.toLong a1
result <- JNI.callMethodE method this' a1'
JNIS.toVoidResult result
-- | @virtual final wait() -> void@
wait'' :: ( this, JNIS.VoidResult void) => this -> JNI.Java void
wait'' this = do
(Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager"
(Prelude.Just method) <- clazz `JNI.getMethod` "wait" JNI.::= JNI.void
this' <- JNI.asObject this
result <- JNI.callMethodE method this'
JNIS.toVoidResult result
现在这已经相当接近,但是即使我尝试手动修补输出源,我也不会用GHC 7.8.4进行编译。
顶部有一个空的import qualified
,导致语法错误。所以我试着通过评论来禁用它。
然后有很多错误消息指向类型声明的各个部分,所以我也对它们进行了评论,希望GHC可能会推断出一些明智的东西。至少在我试图让它发挥作用之前。
然后我收到此错误:
Preprocessing executable 'exp-java' for exp-java-0.1.0.0...
[1 of 2] Compiling DriverManager ( DriverManager.hs, dist/build/exp-java/exp-java-tmp/DriverManager.o )
DriverManager.hs:109:5:
No instance for (JNIS.ObjectResult b3)
arising from a use of ‘JNIS.toObjectResult’
The type variable ‘b3’ is ambiguous
Relevant bindings include
getDrivers :: JNI.Java b3 (bound at DriverManager.hs:105:1)
Note: there are several potential instances:
instance JNIS.UnsafeCast a =>
JNIS.ObjectResult (Prelude.Either JNI.JThrowable (Prelude.Maybe a))
-- Defined in ‘Foreign.Java.Bindings.Support’
instance JNIS.UnsafeCast a =>
JNIS.ObjectResult (Prelude.Either (Prelude.Maybe JNI.JThrowable) a)
-- Defined in ‘Foreign.Java.Bindings.Support’
instance JNIS.UnsafeCast a => JNIS.ObjectResult (Prelude.Maybe a)
-- Defined in ‘Foreign.Java.Bindings.Support’
...plus two others
In a stmt of a 'do' block: JNIS.toObjectResult result
In the expression:
do { (Prelude.Just clazz) <- JNI.getClass "java.sql.DriverManager";
(Prelude.Just method) <- clazz
`JNI.getStaticMethod`
"getDrivers" JNI.::= JNI.object "java.util.Enumeration";
result <- JNI.callStaticMethodE method;
JNIS.toObjectResult result }
In an equation for ‘getDrivers’:
getDrivers
= do { (Prelude.Just clazz) <- JNI.getClass
"java.sql.DriverManager";
(Prelude.Just method) <- clazz
`JNI.getStaticMethod`
"getDrivers" JNI.::= JNI.object "java.util.Enumeration";
result <- JNI.callStaticMethodE method;
.... }
我还不确定如何解决。有什么想法吗?
我的问题2..4在原始问题的最后,就在编辑之前,仍然有效。