<commit_before>{-# LANGUAGE OverloadedStrings, GeneralizedNewtypeDeriving, RecordWildCards,
    DeriveDataTypeable, MultiParamTypeClasses, FunctionalDependencies,
    FlexibleInstances #-}

module Database.Redis.Core (
    Connection(..), connect,
    ConnectInfo(..), defaultConnectInfo,
    Redis(),runRedis,
    RedisTx(..), runRedisTx,
    Queued(..),
    RedisCtx(), MonadRedis(),
    send, recv, sendRequest,
    HostName, PortID(..),
    ConnectionLostException(..),
    auth
) where

import Prelude hiding (catch)
import Control.Applicative
import Control.Monad.Reader
import Control.Monad.State
import Control.Concurrent
import Control.Concurrent.STM
import Control.Exception
import qualified Data.Attoparsec as P
import qualified Data.ByteString as B
import Data.Pool
import Data.Time
import Data.Typeable
import Network
import System.IO
import System.IO.Unsafe

import Database.Redis.Reply
import Database.Redis.Request
import Database.Redis.Types


--------------------------------------------------------------------------------
-- The Redis Monad
--

-- |Context for normal command execution, outside of transactions.
newtype Redis a = Redis (ReaderT RedisEnv IO a)
    deriving (Monad, MonadIO, Functor, Applicative)

-- |Command-context inside of MULTI\/EXEC transactions.
newtype RedisTx a = RedisTx (StateT ([Reply] -> Reply) Redis a)
    deriving (Monad, MonadIO, Functor, Applicative)


-- |A 'Queued' value represents the result of a command inside a transaction. It
--  is a placeholder for the actual result, which will only be available after
--  returning from a 'multiExec' transaction.
data Queued a = Queued ([Reply] -> Either Reply a)

instance Functor Queued where
    fmap f (Queued g) = Queued (fmap f . g)

instance Applicative Queued where
    pure x                = Queued (const $ Right x)
    Queued f <*> Queued x = Queued $ \rs -> do
                                        f' <- f rs
                                        x' <- x rs
                                        return (f' x')

instance Monad Queued where
    return         = pure
    Queued x >>= f = Queued $ \rs -> do
                                x' <- x (rs :: [Reply])
                                let Queued f' = f x'
                                f' rs
                                

class (MonadRedis m) => RedisCtx m result a | m result -> a, m a -> result where
    returnDecode :: Reply -> m a

instance (RedisResult a) => RedisCtx Redis a (Either Reply a) where
    returnDecode = return . decode

instance (RedisResult a) => RedisCtx RedisTx a (Queued a) where
    returnDecode _queued = RedisTx $ do
        f <- get
        put (f . tail)
        return $ Queued (decode . f)

class (Monad m) => MonadRedis m where
    liftRedis :: Redis a -> m a<commit_msg>Remove unnecessary type annotation.<commit_after>{-# LANGUAGE OverloadedStrings, GeneralizedNewtypeDeriving, RecordWildCards,
    DeriveDataTypeable, MultiParamTypeClasses, FunctionalDependencies,
    FlexibleInstances #-}

module Database.Redis.Core (
    Connection(..), connect,
    ConnectInfo(..), defaultConnectInfo,
    Redis(),runRedis,
    RedisTx(..), runRedisTx,
    Queued(..),
    RedisCtx(), MonadRedis(),
    send, recv, sendRequest,
    HostName, PortID(..),
    ConnectionLostException(..),
    auth
) where

import Prelude hiding (catch)
import Control.Applicative
import Control.Monad.Reader
import Control.Monad.State
import Control.Concurrent
import Control.Concurrent.STM
import Control.Exception
import qualified Data.Attoparsec as P
import qualified Data.ByteString as B
import Data.Pool
import Data.Time
import Data.Typeable
import Network
import System.IO
import System.IO.Unsafe

import Database.Redis.Reply
import Database.Redis.Request
import Database.Redis.Types


--------------------------------------------------------------------------------
-- The Redis Monad
--

-- |Context for normal command execution, outside of transactions.
newtype Redis a = Redis (ReaderT RedisEnv IO a)
    deriving (Monad, MonadIO, Functor, Applicative)

-- |Command-context inside of MULTI\/EXEC transactions.
newtype RedisTx a = RedisTx (StateT ([Reply] -> Reply) Redis a)
    deriving (Monad, MonadIO, Functor, Applicative)


-- |A 'Queued' value represents the result of a command inside a transaction. It
--  is a placeholder for the actual result, which will only be available after
--  returning from a 'multiExec' transaction.
data Queued a = Queued ([Reply] -> Either Reply a)

instance Functor Queued where
    fmap f (Queued g) = Queued (fmap f . g)

instance Applicative Queued where
    pure x                = Queued (const $ Right x)
    Queued f <*> Queued x = Queued $ \rs -> do
                                        f' <- f rs
                                        x' <- x rs
                                        return (f' x')

instance Monad Queued where
    return         = pure
    Queued x >>= f = Queued $ \rs -> do
                                x' <- x rs
                                let Queued f' = f x'
                                f' rs
                                

class (MonadRedis m) => RedisCtx m result a | m result -> a, m a -> result where
    returnDecode :: Reply -> m a

instance (RedisResult a) => RedisCtx Redis a (Either Reply a) where
    returnDecode = return . decode

instance (RedisResult a) => RedisCtx RedisTx a (Queued a) where
    returnDecode _queued = RedisTx $ do
        f <- get
        put (f . tail)
        return $ Queued (decode . f)

class (Monad m) => MonadRedis m where
    liftRedis :: Redis a -> m a
{'fraction_non_alphanumeric': 0.11616252013603007, 'fraction_numerical': 0.0, 'mean_word_length': 2.113091922005571, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7028211', 'n_tokens_mistral': 1604, 'n_tokens_neox': 1564, 'n_words': 561}