3

How can I convert the below example to use an external file instead of the embedded lazy text quasi quotes?

{-# LANGUAGE QuasiQuotes, OverloadedStrings #-}
import Text.Shakespeare.Text
import qualified Data.Text.Lazy.IO as TLIO
import Data.Text (Text)
import Control.Monad (forM_)

data Item = Item
    { itemName :: Text
    , itemQty :: Int
    }

items :: [Item]
items =
    [ Item "apples" 5
    , Item "bananas" 10
    ]

main :: IO ()
main = forM_ items $ \item -> TLIO.putStrLn
    [lt|You have #{show $ itemQty item} #{itemName item}.|]

This is from the yesod online book.

Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
Adam Gordon Bell
  • 3,083
  • 2
  • 26
  • 53
  • 1
    From the page you linked, it looks like Yesod uses [this Hamlet function](http://hackage.haskell.org/packages/archive/hamlet/1.1.1/doc/html/src/Text-Hamlet.html#hamletFileWithSettings) to load a template from a file. This looks straightforward, building off of it for your own use should be fairly simple. – bisserlis Oct 09 '12 at 02:44

1 Answers1

3

You can use the textFile function, along the lines of $(textFile "some-file").

Michael Snoyman
  • 31,100
  • 3
  • 48
  • 77
  • 2
    Thanks, but how do I get Language.Haskell.TH.Syntax.Q to some string type? – Adam Gordon Bell Oct 10 '12 at 01:37
  • Same issue. I can get textFile to load the file, but GHC is not happy with the resulting Q Exp. – Ivan Perez May 11 '15 at 22:11
  • 1
    Using Data.Text.Internal.Builder.toLazyText and passing an empty ("" :: Text) to the Exp value created by textFile, I was able to obtain a lazy Text that I could use in my code. See: https://hackage.haskell.org/package/text-1.1.0.1/docs/Data-Text-Internal-Builder.html I would wary against relying on an internal module though. There must be a better solution or, if not, then maybe a small library should be created for this purpose. Felipe Lessa started something like this for emails. – Ivan Perez May 11 '15 at 22:32
  • 1
    I've had the same problem. Using `Builder`'s internal builder works, but variable scoping wasn't quite right. The best solution I found so far is to define `fromFile :: QuasiQuoter` where `fromFile = quoteFile lt` and then use `[fromFile|my_file.txt|]`. – Nicolas Mattia Mar 14 '16 at 11:41