0

Is it possible to add routes dynamically at compile time through a config file by using Template Haskell or any other way.

Scotty has a function addRoute but I want to use it dynamically.

Example

import qualified Data.Text.Lazy as LTB

sampleRoutes :: [(String, LTB.Text)]
sampleRoutes = [("hello", LTB.pack "hello"), ("world", LTB.pack "world")]

I want to iterate over the sampleRoutes array and define routes and responses at compile time.

import Web.Scotty

main = scotty 3000 $ do
  middleware logStdoutDev
  someFunc sampleRoutes
Cactus
  • 27,075
  • 9
  • 69
  • 149
user2512324
  • 791
  • 1
  • 6
  • 21
  • Without using TH I have been able to do `do {middleware logStdoutDev; ((get ("/hello")) (text (LTB.pack ("hello")))) ; ((get ("/world")) (text (LTB.pack ("world"))))}` How can I compose actions dynamically inside the `ScottyM ()`monad based on some list? – user2512324 May 18 '15 at 10:27
  • small *hint*: you can remove (most if not all) of your `LTB.pack` in there if you just use `{-# LANGUAGE OverloadedStrings #-}` (and `Text` instead `String` might be a good idea too if you don't really need the `String = [Char]` part) – Random Dev May 18 '15 at 12:42

1 Answers1

2

OK, so given the above list, I am assuming you are looking to something that is equivalent to writing the following by hand:

{-! LANGUAGE OverloadedStrings #-}
import Web.Scotty
import Data.String

main = scotty 3000 $ do
  middleware logStdoutDev
  get (fromString $ '/' : "hello") (text "hello")
  get (fromString $ '/' : "world") (text "world")

The good news is, there's nothing in there that would need any TH magic!

Remember, addroute / get are just regular functions that return a ScottyM () value. If I have

r1 = get (fromString $ '/' : "hello") (text "hello")
r2 = get (fromString $ '/' : "world") (text "world")

then the preceding main function is exactly equivalent to

main = do
  middleware logStdoutDev
  r1
  r2

This, and the common structure of r1 and r2 suggests the following solution:

import Control.Monad (forM_)

main = do
  middleware logStdoutDev
  forM_ sampleRoutes $ \(name, response) -> 
    get (fromString $ '/':name) (text response)
Cactus
  • 27,075
  • 9
  • 69
  • 149