2016-05-17 69 views
1

假設我有一個啞巴的弗雷格函數,構造了一對Num將值從弗雷格傳遞到Java和返回

newPair :: (Num α, Num β) => α -> β -> (α, β) 
newPair = (,) 
-- alternatively -- newPair x y = (x, y) 

試圖從Java調用這個函數,但是,PreludeBase.CNum<α>PreludeBase.CNum<β>的要求,除了預期Lazy<α>Lazy<β>。同樣與Show類型,其中

showSomething :: (Show α) => α -> String 
showSomething = show 
-- alternatively -- showSomething x = show x 

將需要PreludeBase.CShow<α>除了期望的參數。

將受限制的Frege對象傳遞給Java和從Java傳遞的正確方法是什麼?

回答

2

好問題,因爲這在維基中尚未解釋。

正如在這樣所有情況下,我建議在REPL使用

:java 

命令。例如:

frege> newPair 1 2.3 
frege> :java 

然後,您將獲得一個窗口,其中包含所有活動定義中對應此調用的窗口。簡單的文本搜索可以幫助找到調用newPair的地方。這應該有助於在大多數時候解決這些問題。

在你的情況,相關的部分看起來像:

Console.<Integer, Double>numPair(
    PreludeBase.INum_Int.it, 
    PreludeBase.IReal_Double.it, 
    Thunk.<Integer>lazy(1), 
    Thunk.<Double>lazy(2.3)) 

下面是關於如何類型類和實例命名以及如何在他們得到一個簡短overwiew。

module x.y.Z where 
    class Xable where ... 

這導致了Java的接口,完全合格的名稱

x.y.Z.CXable 

而且這樣的:

導致一些類

a.b.C.IXable_MyType /* implements CXable<TMyType> */ 

如果您的實例定義沒有約束t自己,會有一個你可以使用的單例實例。

a.b.C.IXable_MyType.it 

否則,您需要通過將所有約束作爲參數傳遞給構造函數來構造一個新實例。例如,對於

Maybe Int 

顯示實例將是這個樣子:

new IShow_Maybe(IShow_Int.it) 

因爲實例頭列出了約束的也許元素類型:

instance Show a => Show (Maybe a) 

請注意,您需要充分了解實際類型,不能創建泛型類實例。這在Frege本身中從來都不是問題,因爲所有需要的實例都從調用者傳遞給多態函數。但是,就目前而言,我們對本地函數沒有限制。

你應該需要這樣的事情,你可以只是路過你想作爲參數調用的函數實現在多數情況下的功能。

例如,這不起作用:

pure native myMethod :: Show a => a -> ... 

但這應該:

pure native myMethod :: (a -> String) -> a -> .... 
myMethod show (Just 47) 

上面還有例如Java代碼顯示,描述它並不總是那麼容易。例如,恰巧在Double類型沒有單獨的Num實例,但只有我一個Real這是Num一個子類。不幸的是,只有編譯器知道某些類型實際存在哪些實例,哪些實例是隱式的,也就是說,由一個子類實例提供。同樣,REPL是找出這個問題的最好方法。