{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE Safe                  #-}
{-# LANGUAGE StrictData            #-}
{-# LANGUAGE UndecidableInstances  #-}

-- | Monad class for caching of combined keys
module Network.Tox.Crypto.Keyed where

import           Control.Applicative            (Applicative, pure, (<*>))
import           Control.Monad                  (Monad)
import           Control.Monad.RWS              (RWST)
import           Control.Monad.Random           (RandT)
import           Control.Monad.Reader           (ReaderT)
import           Control.Monad.State            (StateT)
import           Control.Monad.Trans            (lift)
import           Control.Monad.Writer           (WriterT)
import           Data.Monoid                    (Monoid)

import qualified Network.Tox.Crypto.CombinedKey as CombinedKey
import           Network.Tox.Crypto.Key         (CombinedKey, PublicKey,
                                                 SecretKey)

class (Monad m, Applicative m) => Keyed m where
  getCombinedKey :: SecretKey -> PublicKey -> m CombinedKey

instance Keyed m => Keyed (ReaderT r m) where
  getCombinedKey :: SecretKey -> PublicKey -> ReaderT r m CombinedKey
getCombinedKey = (m CombinedKey -> ReaderT r m CombinedKey
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m CombinedKey -> ReaderT r m CombinedKey)
-> (PublicKey -> m CombinedKey)
-> PublicKey
-> ReaderT r m CombinedKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((PublicKey -> m CombinedKey)
 -> PublicKey -> ReaderT r m CombinedKey)
-> (SecretKey -> PublicKey -> m CombinedKey)
-> SecretKey
-> PublicKey
-> ReaderT r m CombinedKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SecretKey -> PublicKey -> m CombinedKey
forall (m :: * -> *).
Keyed m =>
SecretKey -> PublicKey -> m CombinedKey
getCombinedKey
instance (Monoid w, Keyed m) => Keyed (WriterT w m) where
  getCombinedKey :: SecretKey -> PublicKey -> WriterT w m CombinedKey
getCombinedKey = (m CombinedKey -> WriterT w m CombinedKey
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m CombinedKey -> WriterT w m CombinedKey)
-> (PublicKey -> m CombinedKey)
-> PublicKey
-> WriterT w m CombinedKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((PublicKey -> m CombinedKey)
 -> PublicKey -> WriterT w m CombinedKey)
-> (SecretKey -> PublicKey -> m CombinedKey)
-> SecretKey
-> PublicKey
-> WriterT w m CombinedKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SecretKey -> PublicKey -> m CombinedKey
forall (m :: * -> *).
Keyed m =>
SecretKey -> PublicKey -> m CombinedKey
getCombinedKey
instance Keyed m => Keyed (StateT s m) where
  getCombinedKey :: SecretKey -> PublicKey -> StateT s m CombinedKey
getCombinedKey = (m CombinedKey -> StateT s m CombinedKey
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m CombinedKey -> StateT s m CombinedKey)
-> (PublicKey -> m CombinedKey)
-> PublicKey
-> StateT s m CombinedKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((PublicKey -> m CombinedKey)
 -> PublicKey -> StateT s m CombinedKey)
-> (SecretKey -> PublicKey -> m CombinedKey)
-> SecretKey
-> PublicKey
-> StateT s m CombinedKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SecretKey -> PublicKey -> m CombinedKey
forall (m :: * -> *).
Keyed m =>
SecretKey -> PublicKey -> m CombinedKey
getCombinedKey
instance (Monoid w, Keyed m) => Keyed (RWST r w s m) where
  getCombinedKey :: SecretKey -> PublicKey -> RWST r w s m CombinedKey
getCombinedKey = (m CombinedKey -> RWST r w s m CombinedKey
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m CombinedKey -> RWST r w s m CombinedKey)
-> (PublicKey -> m CombinedKey)
-> PublicKey
-> RWST r w s m CombinedKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((PublicKey -> m CombinedKey)
 -> PublicKey -> RWST r w s m CombinedKey)
-> (SecretKey -> PublicKey -> m CombinedKey)
-> SecretKey
-> PublicKey
-> RWST r w s m CombinedKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SecretKey -> PublicKey -> m CombinedKey
forall (m :: * -> *).
Keyed m =>
SecretKey -> PublicKey -> m CombinedKey
getCombinedKey
instance Keyed m => Keyed (RandT s m) where
  getCombinedKey :: SecretKey -> PublicKey -> RandT s m CombinedKey
getCombinedKey = (m CombinedKey -> RandT s m CombinedKey
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m CombinedKey -> RandT s m CombinedKey)
-> (PublicKey -> m CombinedKey)
-> PublicKey
-> RandT s m CombinedKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((PublicKey -> m CombinedKey)
 -> PublicKey -> RandT s m CombinedKey)
-> (SecretKey -> PublicKey -> m CombinedKey)
-> SecretKey
-> PublicKey
-> RandT s m CombinedKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SecretKey -> PublicKey -> m CombinedKey
forall (m :: * -> *).
Keyed m =>
SecretKey -> PublicKey -> m CombinedKey
getCombinedKey

-- | trivial instance: the trivial monad, with no caching of keys
newtype NullKeyed a = NullKeyed { NullKeyed a -> a
runNullKeyed :: a }
instance Functor NullKeyed where
  fmap :: (a -> b) -> NullKeyed a -> NullKeyed b
fmap a -> b
f (NullKeyed a
x) = b -> NullKeyed b
forall a. a -> NullKeyed a
NullKeyed (a -> b
f a
x)
instance Applicative NullKeyed where
  pure :: a -> NullKeyed a
pure = a -> NullKeyed a
forall a. a -> NullKeyed a
NullKeyed
  (NullKeyed a -> b
f) <*> :: NullKeyed (a -> b) -> NullKeyed a -> NullKeyed b
<*> (NullKeyed a
x) = b -> NullKeyed b
forall a. a -> NullKeyed a
NullKeyed (a -> b
f a
x)
instance Monad NullKeyed where
  return :: a -> NullKeyed a
return = a -> NullKeyed a
forall a. a -> NullKeyed a
NullKeyed
  NullKeyed a
x >>= :: NullKeyed a -> (a -> NullKeyed b) -> NullKeyed b
>>= a -> NullKeyed b
f = a -> NullKeyed b
f a
x
instance Keyed NullKeyed where
  getCombinedKey :: SecretKey -> PublicKey -> NullKeyed CombinedKey
getCombinedKey = (CombinedKey -> NullKeyed CombinedKey
forall a. a -> NullKeyed a
NullKeyed (CombinedKey -> NullKeyed CombinedKey)
-> (PublicKey -> CombinedKey) -> PublicKey -> NullKeyed CombinedKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((PublicKey -> CombinedKey) -> PublicKey -> NullKeyed CombinedKey)
-> (SecretKey -> PublicKey -> CombinedKey)
-> SecretKey
-> PublicKey
-> NullKeyed CombinedKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SecretKey -> PublicKey -> CombinedKey
CombinedKey.precompute