davenportw15
davenportw15

Reputation: 157

Monad type mismatch

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

Answers (1)

DiegoNolan
DiegoNolan

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

Related Questions