16

Is there any way to take "things" out of a monad?

I am developing a game, and I am now trying to understand about databases. I found happstack really nice, but I can't get the thing.

For example, I have this function (hope you are familiar with happstack)

getAllThings :: MonadIO m => m [Thing]
getAllThings = do
            elems <- query GetThings
            return elems

So I get m [Things], but I can't use this in my model! For instance

doSomeThingWithThings :: [Thing] -> Something

I googled this and I found nothing.

nbro
  • 15,395
  • 32
  • 113
  • 196
Illiax
  • 1,002
  • 1
  • 8
  • 21
  • 3
    You may enjoy [my comments about the imaginary `magicMonadUnwrap`](http://stackoverflow.com/questions/7154518/unwrapping-a-monad/7156230#7156230) (answer to a similar StackOverflow question) – Dan Burton Sep 06 '11 at 13:36
  • 1
    There is a way to take "things" out of a monad - use [Standard ML](https://www.smlnj.org/sml.html). – atravers Sep 03 '20 at 01:01

2 Answers2

18

You are not supposed to exit IO monad this way (except unsafePerformIO function), but you can still use your function inside it:

process :: MonadIO m => m ()
process = do
          elems <- getAllThings
          let smth = doSomeThingWithThings elems
          -- ...
nbro
  • 15,395
  • 32
  • 113
  • 196
bravit
  • 460
  • 3
  • 11
  • 8
    You can think of it like this: your entire program is IO monad, and your model is bunch of pure functions which are executed inside it. – bravit Sep 06 '11 at 04:34
  • 1
    Yes!! after re thinking my question with your answers, I understand that it has to be this way!, my game is (as you said) pure functions, but user interface is the real ugly world, so the persistence part has to be too! – Illiax Sep 06 '11 at 05:02
2

After elems <- query GetThings the elems is [Thing] so <- inside do is about getting things out of monad (called bind operation). The last statement return put things inside a monad. So either you can call you other function after getting elems and before return or where ever you are calling getAllThings you can use extract the value using <- from the monad and pass it to your function

Ankur
  • 33,367
  • 2
  • 46
  • 72