I got ReaderT from Control.Monad.Reader:
newtype ReaderT r m a = ReaderT { runReaderT :: r -> m a }
and Action from Database.MongoDB.Query:
type Action = ReaderT MongoContext
Query functions of MongoDB are something like this:
delete :: MonadIO m => Selection -> Action m ()
I'm trying to use pattern mathing with Action m () to check if it is Action IO () or Action _ ()
A simple case like this
case x of
Action IO () -> True
Action _ () -> False
doesn't work, because Action is not a data constructor. Probably I should use something like this:
case x of
ReaderT MongoContext IO () -> True
ReaderT MongoContext _ () -> False
But then I get an error:
The constructor ‘ReaderT’ should have 1 argument, but has been given 3
In the pattern: ReaderT MongoContext IO ()
In a case alternative:
ReaderT MongoContext IO ()
Should I pass MongoContext -> IO () instead? I'm out of ideas, please help me with that expression. Thanks <3
IO is a type, you absolutely cannot case match against it, it only exists at compile time.
In general, if you have a type variable constrained by a type class, you can only call things supported by that type class. You cannot know which particular type it is unless the typeclass implements methods for inspecting it, like Typeable. Neither Monad nor MonadIO implement this kind of run-time type discrimination, so what you want is, by design, not possible.
Also note that, you don't need to know "which m" delete is, since it's specialized to whatever m that YOU want it to be, so long as it is an instance of MonadIO. You can simply declare deleteIO sel = delete sel :: Action IO ()
What are you actually trying to get done here?
As Steven Armstrong said, what you're trying to do is very weird, you cannot pattern match on IO because is an abstract data type (constructors aren't visible) and if I were you I would rethink what I'm trying to achieve. Having said that, Haskell still gives you a way of inspecting types at runtime using Typeable eg (inside a ghci session):
import Data.Typeable
import Control.Monad.Trans.Reader
type MyType = ReaderT String IO
f :: MyType ()
f = ReaderT $ \env -> putStrLn env
checkF :: Typeable a => MyType a -> Bool
checkF x = case show (typeOf x) of
"ReaderT * [Char] IO ()" -> True
_ -> False
-- checkF f => True
Related
I am trying to use the bracket function from Exception.Safe Package which has a return type of
forall m a b c. MonadMask m => m a -> (a -> m b) -> (a -> m c) -> m c
This implies that my monad stack must have the Mask monad added to the stack ?
My calling function looks like this
sendMessage :: String -> Config.KafkaP (Either KafkaError ())
sendMessage msg=do
getProperties <- producerProps
let
mkProducer = newProducer getProperties
clProducer (Left _) = return ()
clProducer (Right prod) = closeProducer prod
runHandler (Left err) = return $ Left err
runHandler (Right prod) = messageSender prod msg
res <- bracket mkProducer clProducer runHandler
return res
And config.KakfaP has the type
ReaderT ProducerConfig IO a
And the error I get is ,
No instance for (exceptions-0.10.0:Control.Monad.Catch.MonadMask
Config.KafkaP)
arising from a use of ‘bracket’
Does this mean the monad stack needs to be something like this
Mask (ReaderT ProducerConfig IO a)
Ideally I would want the function to return what the run Handler returns which is Config.KafkaP (Either KafkaError ()) ,or anything more robust .
Adding a solution based on an answer
sendMessage :: String -> Config.KafkaP (Either KafkaError ())
sendMessage msg=do
getProperties <- producerProps
let
mkProducer = newProducer getProperties
--newProducer :: MonadIO m => ProducerProperties -> m (Either KafkaError KafkaProducer)
--mkProducer :: Config.KafkaP (Either KafkaError KafkaProducer)
clProducer (Left _) = return ()
clProducer (Right prod) = closeProducer prod
--closeProducer :: MonadIO m => KafkaProducer -> m ()
--clProducer :: Config.KafkaP (Either () ()) -- ??
runHandler (Left err) = return $ Left err
runHandler (Right prod) = messageSender prod msg
--messageSender :: KafkaProducer -> String -> Config.KafkaP (Either KafkaError ())
--runHandler :: Config.KafkaP (Either KafkaError ()) -- ??
Config.KafkaP $ bracket (Config.runK mkProducer) (Config.runK .clProducer) (Config.runK .runHandler)
If you were using the type ReaderT ProducerConfig IO a directly, there wouldn't be a problem, because the exceptions package provides an instance
MonadMask IO
That says you can use bracket with IO, and another instance
MonadMask m => MonadMask (ReaderT r m)
That says that if the base monad is an instance of MonadMask, then ReaderT over that monad is also an instance of MonadMask.
Notice that MonadMask is not a transformer that is part of the monad stack. Instead, it is a constraint that says "this monad stack supports masking / bracketing operations".
If you were using a type synonym like
type KafkaP a = ReaderT ProducerConfig IO a
there wouldn't be a problem either, because type synonyms don't create a new type, they just give an alias to an exiting one. One can still make use of all the existing typeclass instances for the type.
You mention in the comments that KafkaP is a newtype. A newtype is a cheap way of creating, well, a new type out of another. It's basically a constructor that holds a value of the original type.
And that's the problem. Because it is a new type, it doesn't share automatically all the typeclass instances of the old one. In fact, having different typeclass instances in newtypes is one of the main motivations for using newtypes!
What can be done? Well, supposing the newtype constructor is exported (sometimes they are hidden for purposes of encapsulation) you could unwrap the KafkaPs actions into ReaderT ProducerConfig IO a before sending them into bracket, and then re-wrap the result into KafkaP again. Some of the parameters are KafkaP-returning functions, so you'll probably need to throw in some function composition as well. Perhaps something like (assuming KafkaP is the name of the constructor, and runKafkaP the name of the corresponding accessor):
KafkaP $ bracket (runKafkaP mkProducer) (runKafkaP . clProducer) (runKafkaP . runHandler)
All this wrapping and unwrapping is tedious; sometimes using coerce from Data.Coerce can help. But this only works when the newtype constructor is exported.
You might also think of defining your own MonadMask instance for KafkaP using the technique above. This can be done, but instances which are defined neither in the module that defines the typeclass nor in the module that defines the type are called orphan instances and are somewhat frowned upon.
I have been learning haskell for some time and I just finished reading 'Learn you a Haskell for great good'. My question comes from an assignment I'm currently trying to complete. Basically, I have been using the Snap Framework and I'm currently having a hard time understanding how the state (in this case the Request + Response object, the MonadSnap) is mutated when making calls such the one below:
modifyResponse :: MonadSnap m => (Response -> Response) -> m ()
I can't quite figure out how the modifyResponse method mutates the underlying MonadSnap while only specifying it as a type constraint.
I've come across this similar concept while searching for the answer and I believe the same answer would apply if I wanted to keep a state and make the below functions work as intended, like the OP proposed in this answer:
instance M Monad where ...
-- Modify the counter and do not produce any result:
incrementCounter :: M ()
decrementCounter :: M ()
-- Get the current value of the counter
readCounter :: M Integer
Here's the source code for modifyResponse:
modifyResponse :: MonadSnap m => (Response -> Response) -> m ()
modifyResponse f = liftSnap $
smodify $ \ss -> ss { _snapResponse = f $ _snapResponse ss }
The only function in the MonadSnap typeclass is liftSnap, and the only pre-defined instance of the typeclass is the Snap monad (where it's defined as liftSnap = id).
It's just a tiny bit of indirection in order to allow the function to work with other types that implement MonadSnap also. It makes working with Monad Transformer stacks much easier. The signature could have been:
modifyResponse :: (Response -> Response) -> Snap ()
Now, perhaps your next question is: "How does smodify work?"
Here's the source code:
smodify :: (SnapState -> SnapState) -> Snap ()
smodify f = Snap $ \sk _ st -> sk () (f st)
As you can see, it's not magic, just functions. The internal SnapState is being hidden from you, because you don't need to know the internals of Snap in order to use it. Just like how you don't need to know the internals of the IO monad in order to use it.
Every instance of MonadSnap must provide a liftSnap method:
-- | 'MonadSnap' is a type class, analogous to 'MonadIO' for 'IO', that makes it
-- easy to wrap 'Snap' inside monad transformers.
class (Monad m, MonadIO m, MonadBaseControl IO m, MonadPlus m, Functor m,
Applicative m, Alternative m) => MonadSnap m where
-- | Lift a computation from the 'Snap' monad.
liftSnap :: Snap a -> m a
The means that any time there's a MonadSnap m it's easy to convert a concrete Snap a into m a via liftSnap.
Modifying a concrete Snap's state is done by succeeding with the new SnapState and a unit () value. sk is the success continuation for what to do on success.
-- | Local Snap monad version of 'modify'.
smodify :: (SnapState -> SnapState) -> Snap ()
smodify f = Snap $ \sk _ st -> sk () (f st)
{-# INLINE smodify #-}
modifyResponse lifts smodify from Snap a to MonadSnap m => m a. The function f passed to smodify is a function that modifies only the _snapResponse field of the SnapState record.
modifyResponse :: MonadSnap m => (Response -> Response) -> m ()
modifyResponse f = liftSnap $
smodify $ \ss -> ss { _snapResponse = f $ _snapResponse ss }
{-# INLINE modifyResponse #-}
GHC is saying my function is too general to be passed as an argument.
Here is a simplified version that reproduces the error:
data Action m a = SomeAction (m a)
runAction :: Action m a -> m a
runAction (SomeAction ma) = ma
-- Errors in here
actionFile :: (Action IO a -> IO a) -> String -> IO ()
actionFile actionFunc fileName = do
actionFunc $ SomeAction $ readFile fileName
actionFunc $ SomeAction $ putStrLn fileName
main :: IO ()
main =
actionFile runAction "Some Name.txt"
This is what the error says:
• Couldn't match type ‘a’ with ‘()’
‘a’ is a rigid type variable bound by
the type signature for:
actionFile :: forall a. (Action IO a -> IO a) -> String -> IO ()
at src/Lib.hs:11:15
Expected type: Action IO a
Actual type: Action IO ()
The compiler wants me to be more specific in my type signature, but I can't because I will need to use the parameter function with different types of arguments. Just like in my example I pass it an Action IO () and an Action IO String.
If I substitute (Action IO a -> IO a) -> String -> IO () for (Action IO () -> IO ()) -> String -> IO (), like the compiler asked, the invocation with readFile errors because it outputs an IO String.
Why is this happening and what should I do to be able to pass this function as an argument?
I know that if I just use runAction inside my actionFile function everything will work, but in my real code runAction is a partially applied function that gets built from results of IO computations, so it is not available at compile time.
This is a quantifier problem. The type
actionFile :: (Action IO a -> IO a) -> String -> IO ()
means, as reported by the GHC error,
actionFile :: forall a. (Action IO a -> IO a) -> String -> IO ()
which states the following:
the caller must choose a type a
the caller must provide a function g :: Action IO a -> IO a
the caller must provide a String
finally, actionFile must answer with an IO ()
Note that a is chosen by the caller, not by actionFile. From the point of view of actionFile, such type variable is bound to a fixed unknown type, chosen by someone else: this is the "rigid" type variable GHC mentions in the error.
However, actionFile is calling g passing an Action IO () argument (because of putStrLn). This means that actionFile wants to choose a = (). Since the caller can choose a different a, a type error is raised.
Further, actionFile also wants to call g passing an Action IO String argument (because of readFile), so we also want to choose a = String. This implies that g must accept the choice of whatever a we wish.
As mentioned by Alexis King, a solution could be to move the quantifier and use a rank-2 type:
actionFile :: (forall a. Action IO a -> IO a) -> String -> IO ()
This new type means that:
the caller must provide a function g :: forall a. Action IO a -> IO a
the caller of g (i.e., actionFile) must choose a
the caller of g (i.e., actionFile) must provide an Action IO a
finally, g must provide an IO a
the caller must provide a String
finally, actionFile must answer with an IO ()
This makes it possible to actionFile to choose a as wanted.
I am attempting to use the IO monad in a Spock application. The following code does not compile:
get "api/entities" $ do
entities <- loadEntities
let e1 : xs = entities
text $ note e1
loadEntities has the type IO [Entity]
The error is Couldn't match type ‘ActionT IO ()’ with ‘t0 -> IO b0’
Is Spock using a monad other than IO? If so, how do I get the result of loadEntities?
Writing answer so people can see a better explanation.
If you look at get it has the type.
get :: MonadIO m => SpockRoute -> ActionT m () -> SpockT m ()
ActionT is a monad transformer and it requires in inner monad to have an instance of MonadIO. If we look at the typeclass MonadIO it has a function
liftIO :: IO a -> m a
This means every that you call execute functions of the type IO a in that stack by using liftIO. ActionT has an instance of MonadIO also and which is the one you are using here to call your IO function. So to call loadEntities you had to
entities <- liftIO loadEntities
If you end of calling a certain function like that a lot you can create a separate module import it qualified and export a more friendly one.
module Lifted (loadEntities) where
import qualified SomeModule as IO
loadEntities :: MonadIO m => m Entities
loadEntities = liftIO IO.loadEntities
This will make it so you don't always have you use liftIO
I've got a bunch of stateful functions inside a State monad. At one point in the program there needs to be some IO actions so I've wrapped IO inside a StateT getting a pair of types like this:
mostfunctions :: State Sometype a
toplevel :: StateT Sometype IO a
To keep things simple I don't want pass the IO context into the main set of functions and I would like to avoid wrapping them in the monad stack type. But in order to call them from the toplevel function I need something akin to a lift, but I'm not trying to lift a value from the inner monad. Rather I want to convert the state in the StateT monad into something equivalent in the State monad. To do this I've got the following:
wrapST :: (State Sometype a) -> StateT Sometype IO a
wrapST f = do s <- get
let (r,s2) = runState f s
put s2
return r
This then get used to interleave things like the following:
toplevel = do liftIO $ Some IO functions
wrapST $ Some state mutations
liftIO $ More IO functions
....
It seems like a fairly obvious block of code so I'm wondering does this function have a standard name, and it is already implemented somewhere in the standard libraries? I've tried to keep the description simple but obviously this extends to pulling one transformer out of a stack, converting the wrapped value to the cousin of the transformer type, skipping the monads below in the stack, and then pushing the results back in at the end.
It may be a good idea to refactor your code to use the type StateT SomeType m a instead of State SomeType a, because the first one is compatible to an arbitrary monad stack. If you'd change it like this, you don't need a function wrapST anymore, since you can call the stateful functions directly.
Okay. Suppose you have a function subOne :: Monad m => State Int Int:
subOne = do a <- get
put $ a - 1
return a
Now, change the types of all functions like this one from State SomeType a to StateT SomeType m a, leaving m as is. This way, your functions can work on any monadic stack. For those functions, that require IO, you can specify, that the monad at the bottom must be IO:
printState :: MonadIO m => StateT Int m ()
printState = do a <- get
liftIO $ print a
Now, it should be possible to use both functions together:
-- You could use me without IO as well!
subOne :: Monad m => StateT Int m ()
subOne = do a <- get
put $ a - 1
printState :: MonadIO m => StateT Int m ()
printState = do a <- get
liftIO $ print a
toZero :: StateT Int IO ()
toZero = do subOne -- A really pure function
printState -- function may perform IO
a <- get
when (a > 0) toZero
PS: I use GHC 7, some of the libs changed midway, so it might be a bit different on GHC 6.
A more direct answer to your question: the function hoist does exactly what you're describing in a slightly more generic way. Example usage:
import Control.Monad.State
import Data.Functor.Identity
import Control.Monad.Morph
foo :: State Int Integer
foo = put 1 >> return 1
bar :: StateT Int IO Integer
bar = hoist (return . runIdentity) foo
hoist is part of the MFunctor class, which is defined like this:
class MFunctor t where
hoist :: Monad m => (forall a. m a -> n a) -> t m b -> t n b
There are instances for most monad tranformers, but not ContT.