How can I use an `IO String` inside a Spock request handler?
Asked Answered
N

1

5

I have the following function that produces a random string of characters in multiples of 1024:

import System.Random

rchars :: Int -> [IO Char]
rchars n = map (\_ -> randomRIO ('a', 'z')) [n | n <- [0..n]] -- a wasteful "iteration"-like func

rstr :: Int -> IO String
rstr n = sequence $ rchars (1024 * n)

I want to expose this to the web using Spock, for example:

import Data.Monoid
import Data.Text
import Lib
import Web.Spock.Safe

main :: IO ()
main =
    runSpock 8080 $ spockT id $
    do get root $
           redirect "/data/1"
       get ("data" <//> var) $ \n ->
          do
           str <- rstr n
           text ("boo:" <> str <> "!")

but this is incorrect, as the innermost do-block yields an IO b0, not the expected type from Spock:

Couldn't match type ‘ActionT IO ()’ with ‘IO b0’
Expected type: Int -> IO b0
  Actual type: hvect-0.2.0.0:Data.HVect.HVectElim
                 '[Int] (ActionT IO ())
The lambda expression ‘\ n -> ...’ has one argument,
but its type ‘hvect-0.2.0.0:Data.HVect.HVectElim
                '[Int] (ActionT IO ())’
has none
In the second argument of ‘($)’, namely
  ‘\ n
     -> do { str <- rstr n;
             text ("boo:" <> str <> "!") }’
In a stmt of a 'do' block:
  get ("data" <//> var)
  $ \ n
      -> do { str <- rstr n;
              text ("boo:" <> str <> "!") }

How can I use my IO-driven random string function inside the Spock get request handler?

Niedersachsen answered 13/2, 2016 at 15:47 Comment(0)
A
7

The ActionT type is an instance of MonadIO typeclass. That means you can use liftIO to perform IO actions inside this monad. In your case you seem to need liftIO $ rstr n instead of plain rstr n.

This demonstrates what I'm referring to:

import Control.Monad.IO.Class
...
main :: IO ()
main =
    runSpock 8080 $ spockT id $
    do get root $
           redirect "/data/1"
       get ("data" <//> var) $ \n ->
          do
           str <- liftIO $ rstr n
           text $ pack str
Autosuggestion answered 13/2, 2016 at 17:32 Comment(3)
From where to I import liftIO?Niedersachsen
haddock.stackage.org/lts-5.1/transformers-0.4.2.0/…Autosuggestion
And here you can search for modules/functions: stackage.org/lts-5.1/hoogle?q=liftIO You can even search by type!Autosuggestion

© 2022 - 2024 — McMap. All rights reserved.