Передача значений из Frege в Java и обратно
Предположим, у меня есть немая функция Фреге, которая создает пару Num
s.
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?
1 ответ
Хороший вопрос, так как это еще не объяснено в вики.
Как и во всех подобных случаях, я рекомендую использовать
:java
Команда в REPL. Например:
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))
Вот краткий обзор того, как называются классы типов и экземпляры, и как вы можете их получить.
module x.y.Z where
class Xable where ...
В результате получается Java-интерфейс с полным именем
x.y.Z.CXable
И это:
module a.b.C where
import x.y.Z
data MyType ... = ....
instance Xable MyType where ...
результаты в каком-то классе
a.b.C.IXable_MyType /* implements CXable<TMyType> */
Если ваше определение экземпляра не имеет самих ограничений, будет единственный экземпляр, который вы можете использовать.
a.b.C.IXable_MyType.it
В противном случае вам нужно создать новый экземпляр, передав все ограничения в качестве аргумента конструктору. Например, экземпляр Show для
Maybe Int
будет выглядеть примерно так:
new IShow_Maybe(IShow_Int.it)
поскольку заголовок экземпляра перечисляет ограничение для типа элемента Maybe:
instance Show a => Show (Maybe a)
Обратите внимание, что вам нужно полностью знать фактический тип, вы не можете создать экземпляр класса универсального типа. Это никогда не является проблемой в самом Фреге, так как все необходимые экземпляры передаются полиморфной функции от вызывающей стороны. Тем не менее, у нас нет ограничений в нативных функциях.
Если вам нужно что-то подобное, вы можете достичь функциональности в большинстве случаев, просто передав функцию, которую вы хотите вызвать в качестве аргумента.
Например, это не работает:
pure native myMethod :: Show a => a -> ...
но это должно:
pure native myMethod :: (a -> String) -> a -> ....
myMethod show (Just 47)
Приведенный выше пример java-кода также показывает, что это не всегда так просто, как описано. Например, так случилось, что Double
тип не имеет отдельного Num
экземпляр, но только один для Real
который является подклассом Num
, К сожалению, только компилятор знает, какие экземпляры на самом деле присутствуют для некоторого типа, а какие являются неявными, то есть предоставляются экземпляром для подкласса. Опять же, REPL - лучший способ выяснить это.