Skip to content

Instantly share code, notes, and snippets.

@puffnfresh
Created June 15, 2013 01:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save puffnfresh/5786337 to your computer and use it in GitHub Desktop.
Save puffnfresh/5786337 to your computer and use it in GitHub Desktop.
Something like what I want in an FFI to the JVM.
module Java where
-- Small example of the type of interop I would like with Java
import Control.Monad.IO.Class
import Control.Monad.Trans.Maybe
import Control.Monad.Trans.Either
-- Pretend these actually came from Java
type Exception = String
type LinkedList = []
-- Monadic Java interop
newtype Java a = Java { runJava :: MaybeT (EitherT Exception IO) a }
instance Monad Java where
j >>= f = Java (runJava j >>= runJava . f)
return = liftIO . return
instance MonadIO Java where
liftIO = Java . MaybeT . EitherT . fmap (Right . Just)
-- FFI function (pretend impl came from Java)
java_util_LinkedList_get :: Int -> IO (LinkedList a) -> Java a
java_util_LinkedList_get i = liftIO . fmap (!! i)
-- Haskell
plusTop :: IO (LinkedList Int) -> Java Int
plusTop l = do
a <- java_util_LinkedList_get 0 l
b <- java_util_LinkedList_get 1 l
return (a + b)
main :: IO ()
main = do
-- Pretend the list came from Java
let javaList = return [1, 2, 3]
javaResult <- runEitherT . runMaybeT . runJava $ plusTop javaList
case javaResult of
Right (Just result) -> print result -- 3
Right Nothing -> putStrLn "Got a null pointer"
Left exception -> putStrLn "Got exception:" >> print exception
@mmhelloworld
Copy link

Here is a possible translation to Frege:

module hellofrege.Java where

data LinkedList a = native java.util.LinkedList where
    native add :: Mutable s (LinkedList a) -> a -> ST s Bool
    native get :: Mutable s (LinkedList a) -> Int -> ST s (Maybe a)
    native new :: () -> STMutable s (LinkedList a)

    fromFregeList :: [a] -> STMutable s (LinkedList a)
    fromFregeList xs = LinkedList.new () >>= loop xs where
        loop (x:xs) jlist = LinkedList.add jlist x >> loop xs jlist
        loop [] jlist = return jlist

plusTop :: Mutable s (LinkedList Int) -> ST s (Maybe Int)
plusTop xs = do
    a <- xs.get 0
    b <- xs.get 1
    return ((+) <$> a <*> b)

data Exception = native java.lang.Exception
derive Exceptional Exception

data NullPointerException = native java.lang.NullPointerException
derive Exceptional NullPointerException

pure native showThrowable toString :: Throwable -> String

main _ = do
    javaList <- LinkedList.fromFregeList [1, 2, 3]
    try (\xs -> plusTop xs >>= (println . maybe "Got a null pointer" show)) javaList 
        `catch` (\(npe :: NullPointerException) -> println $ showThrowable npe)
        `catch` (\(exception :: Exception) -> println $ showThrowable exception)

Here try and catch are just ordinary functions and Maybe a on LinkedList.get enables Frege automatically handle null elements.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment