Write type signatures for your functions to capture what they should do. Write them before you write the implementation, then you can use the type signatures, and the better error messages you get from the compiler if it knows what type you want to have, to check that the implementation does [or at least has a chance to do] what you want.
Let us look at the problem children, and what they actually do:
From acid-state
we use
update' :: (UpdateEvent event, MonadIO m) => AcidState (EventState event) -> event -> m (EventResult event)
for
insertItem db name itemName comment count = withAccount db name newItem
where item = Item { itemName = itemName, itemComment = comment, itemCount = count, itemStatus = Need }
newItem account = update' db $ NewItem account item
Now let's see what sort of type that would produce. From the use of
withAccount :: MonadIO m => AcidState GoGetDB -> String -> (Account -> a) -> m (Maybe a)
we see that the result has type
m (Maybe a)
for some MonadIO m
, where a
is the result type of newItem
. Now,
newItem account = update' db something
so
newItem :: MonadIO mio => Account -> mio (EventResult type_of_something)
and thus the result type of insertItem
would be
m (Maybe (mio (EventResult type_of_something)))
and in
newItem db user itemName comment count = do
Model.insertItem db user itemName comment count
listItems db user
the compiler doesn't know which MonadIO mio
it should use in the second line. Thus the type variable mio
is ambiguous.
Note that specifying the type variable there would still not do what you presumably want. I expect that you actually want to execute the update'
, and not only compute the action that would update the database when executed.
For insertItem
, if it should indeed update the database, withAccount
as it stands is not useful. You could maybe use something like
withAccountM :: MonadIO m => AcidState GoGetDB -> String -> (Account -> m a) -> m (Maybe a)
withAccountM db name fn = do
maybeAccount <- query' db $ AccountByName name
case maybeAccount of
Nothing -> return Nothing
Just acct -> do
result <- fn acct
return $ Just result
(not tested, could still be entirely wrong) to actually execute the update'
.
The problems and probable fixes are similar for changItemStatus
.