Now and again I keep running into Haskell code where I feel like I should be able to use mapM
to make operating over the monads cleaner, but if I have two computations of type m (t a)
, and perhaps there is another operation that uses t
, something like a -> t a
(typically this is Maybe
)... say I have this persistent code:
findDealership :: MonadIO m => Key Vehicle -> SqlPersistT m (Maybe (Entity Dealership))
findDealership vehicleKey = mapM selectDealership (getVehicleDealership vehicleKey)
getVehicleDealership :: MonadIO m => Key Vehicle -> SqlPersistT m (Maybe (Key Dealership))
getVehicleDealership vehicleKey =
(\x -> x >>= vehicleDealershipId . entityVal) <$> getEntity vehicleKey
selectDealership :: MonadIO m => Key Dealership -> SqlPersistT m (Maybe (Entity Dealership))
selectDealership dealershipKey = selectFirst [DealershipId ==. dealershipKey] []
Where vehicleDealershipId
is a field of type Maybe (Key Dealership)
, the above code will not compile and I'm unable to work out the right combination of >>=
's and mapM
's.... I feel this problem is a bit like the one mapM
is solving, only there is another level of monad in there... you can end up with SqlPersistT m (Maybe (Maybe (Maybe (Key Dealership))))
but obviously I need the inner type to be completely flattened...
Error output for the above code:
• Couldn't match type ‘Control.Monad.Trans.Reader.ReaderT
SqlBackend m0’
with ‘Maybe’
Expected type: SqlPersistT m (Maybe (Entity Dealership))
Actual type: Control.Monad.Trans.Reader.ReaderT
SqlBackend
m
(Control.Monad.Trans.Reader.ReaderT
SqlBackend m0 (Maybe (Entity Dealership)))
• In the expression:
mapM selectDealership $ getVehicleDealership vehicleKey
In an equation for ‘findDealership’:
findDealership vehicleKey
= mapM selectDealership $ getVehicleDealership vehicleKey
|
46 | findDealership vehicleKey = mapM selectDealership $ getVehicleDealership vehicleKey
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
and:
• Couldn't match type ‘Maybe (Key Dealership)’
with ‘Key Dealership’
Expected type: Control.Monad.Trans.Reader.ReaderT
SqlBackend m0 (Key Dealership)
Actual type: SqlPersistT m0 (Maybe (Key Dealership))
• In the second argument of ‘($)’, namely
‘getVehicleDealership vehicleKey’
In the expression:
mapM selectDealership $ getVehicleDealership vehicleKey
In an equation for ‘findDealership’:
findDealership vehicleKey
= mapM selectDealership $ getVehicleDealership vehicleKey
|
46 | findDealership vehicleKey = mapM selectDealership $ getVehicleDealership vehicleKey
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^