Reputation: 157
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?
Upvotes: 1
Views: 92
Reputation: 3766
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
Upvotes: 5