tweag / inline-java

Haskell/Java interop via inline Java code in Haskell modules.
BSD 3-Clause "New" or "Revised" License
229 stars 15 forks source link

Use an abstract monad in the linear interfaces #128

Closed facundominguez closed 4 years ago

facundominguez commented 5 years ago

The linear interfaces were using Linear.IO, that might not be particularly easy to integrate in applications which use other monads.

I propose here a class to lift non-linear monads into linear monads. jni uses this to offer operations that run on any linear monad that can lift the non-linear IO.

class (Linear.Monad m, NonLinear.Monad (LiftedM m)) => MonadLift m where
  type LiftedM m :: * -> *
  lift :: LiftedM m a -> m a
  liftU :: LiftedM m a -> m (Unrestricted a)

Thus, an application can provide an instance of Linear.Monad for any wrapper of a regularly looking monadic stack. e.g.

data App a = App (ReaderT Env IO a)
  deriving (Monad, Functor, Applicative, MonadIO)

data LinearApp a = LinearApp (App a)

instance Linear.Monad LinearApp where
  ...

instance Linear.MonadLift LinearApp where
  type LiftedM LinearApp = App
  lift = LinearApp
  liftU = LinearApp . fmap Unrestricted
b-mehta commented 5 years ago

This proposal sounds good to me. I think Control.Monad.Lift.Linear in linear-base would be an appropriate place for the MonadLift class, and MonadIO can live in Control.Monad.IO.Class.

facundominguez commented 5 years ago

I have moved the Extra modules for linear-base to https://github.com/tweag/linear-base/pull/64