Return do 块中多个字符串中的单个字符串
Return a single string from multiple strings in a do block
我正在尝试实现类似于 HaTeX 中编程的东西,程序员可以将 LaTeX 命令逐行编写为文本。他们的例子之一如下:
-- Body with a section.
theBody :: Monad m => LaTeXT_ m
theBody = do
maketitle
section "Hello"
"This is a simple example using the "
hatex
" library. "
-- 'textbf' turns characters to bold font (as you already may know).
textbf "Enjoy!"
" "
完整示例:
https://github.com/Daniel-Diaz/HaTeX/blob/master/Examples/simple.hs
到目前为止,我已经取得了以下成就:
module Main
where import System.IO
writeContent :: String
writeContent = do
"Some text. "
++ "Some more text. "
++ "This should all compile into a single line "
++ "and be output to the screen."
main :: IO ()
main = do
putStr $ writeContent
但我真的很想去掉 ++
运算符。
我知道 Strings
和 ++
比 Text
效率低,所以一旦我学到更多,最终会改变它。我对 Haskell 还是很陌生。我试过查看 HaTeX 源代码,但有些部分在一行中实现了太多步骤,所以想一次构建它的小步骤。
您可以使用 writer monad:
import Control.Monad.Trans.Writer
writeContent :: Writer String ()
writeContent = do
tell "Some text. "
tell "Some more text. "
tell "This should all compile into a single line "
tell "and be output to the screen."
main :: IO ()
main = do
putStr $ execWriter writeContent
要在没有像 tell
这样的额外(可见)函数调用的情况下执行此操作,您需要 OverloadedStrings
extension:
{-# LANGUAGE GADTs, GeneralizedNewtypeDeriving, OverloadedStrings
#-}
import Control.Monad.Trans.Writer
import Data.String
newtype StringBuilder a =
StringBuilder (Writer String a)
deriving (Functor, Applicative, Monad)
instance (a ~ ()) => IsString (StringBuilder a) where
fromString = StringBuilder . tell
buildString :: StringBuilder () -> String
buildString (StringBuilder w) = execWriter w
writeContent :: StringBuilder ()
writeContent = do
"Some text. "
"Some more text. "
"This should all compile into a single line "
"and be output to the screen."
main :: IO ()
main = do
putStr $ buildString writeContent
我正在尝试实现类似于 HaTeX 中编程的东西,程序员可以将 LaTeX 命令逐行编写为文本。他们的例子之一如下:
-- Body with a section.
theBody :: Monad m => LaTeXT_ m
theBody = do
maketitle
section "Hello"
"This is a simple example using the "
hatex
" library. "
-- 'textbf' turns characters to bold font (as you already may know).
textbf "Enjoy!"
" "
完整示例: https://github.com/Daniel-Diaz/HaTeX/blob/master/Examples/simple.hs
到目前为止,我已经取得了以下成就:
module Main
where import System.IO
writeContent :: String
writeContent = do
"Some text. "
++ "Some more text. "
++ "This should all compile into a single line "
++ "and be output to the screen."
main :: IO ()
main = do
putStr $ writeContent
但我真的很想去掉 ++
运算符。
我知道 Strings
和 ++
比 Text
效率低,所以一旦我学到更多,最终会改变它。我对 Haskell 还是很陌生。我试过查看 HaTeX 源代码,但有些部分在一行中实现了太多步骤,所以想一次构建它的小步骤。
您可以使用 writer monad:
import Control.Monad.Trans.Writer
writeContent :: Writer String ()
writeContent = do
tell "Some text. "
tell "Some more text. "
tell "This should all compile into a single line "
tell "and be output to the screen."
main :: IO ()
main = do
putStr $ execWriter writeContent
要在没有像 tell
这样的额外(可见)函数调用的情况下执行此操作,您需要 OverloadedStrings
extension:
{-# LANGUAGE GADTs, GeneralizedNewtypeDeriving, OverloadedStrings
#-}
import Control.Monad.Trans.Writer
import Data.String
newtype StringBuilder a =
StringBuilder (Writer String a)
deriving (Functor, Applicative, Monad)
instance (a ~ ()) => IsString (StringBuilder a) where
fromString = StringBuilder . tell
buildString :: StringBuilder () -> String
buildString (StringBuilder w) = execWriter w
writeContent :: StringBuilder ()
writeContent = do
"Some text. "
"Some more text. "
"This should all compile into a single line "
"and be output to the screen."
main :: IO ()
main = do
putStr $ buildString writeContent