haskelluuidhaskell-spock

Haskell Spock IO within GET Route ActionCtxT Error


I try to return a uuid within a route definition for a web app (Spock Webserver).

A route is pretty simple to define

get("PATH") $ do
 text "Hello World"

Now I try to return a uuid via nextRandom from the Data.UUID.V1 module. The function returns a IO(Maybe UUID) value.

So I thought, since I am in IO and work with another IO I have to do bind the value simply with <-, like so:

get ("id") $ do
    uuid<-nextUUID
    json . pack $ show $ uuid

But the compiler says no:

Couldn't match type ‘ActionCtxT ctx0 m0’ with ‘IO’
      Expected type: IO b0
        Actual type: ActionCtxT ctx0 m0 b0
    • In a stmt of a 'do' block: json . pack $ show $ uuid
      In the second argument of ‘($)’, namely
        ‘do { uuid <- nextUUID;
              json . pack $ show $ uuid }’

Why is it throwing that error? I could easily create the uuid with a simple print example, but within Spock I don't understand what the ActionCtxT does and why I can't do the uuid IO in it.


Solution

  • So I thought, since I am in IO and work with another IO

    That's the trouble here, when you're routing in Spock, you're not in IO. The error message tells you what context you're really in: ActionCtxT ctx0 m0. According to the docs, that's a monad transformer stack that bundles effects and state.

    You can "lift" an IO computation into the right type using liftIO.

    get ("id") $ do
        uuid <- liftIO nextUUID
        json . pack $ show $ uuid