如何将 Scotty 参数转换为字符串
How to convert Scotty parameter as String
我是 Haskell 的新手,正在使用 Scotty 网络库测试一些概念。
但是,我无法使简单的 hello world 页面正常工作。
我坚持将参数转换为字符串并应用于另一个函数。
这是尚未运行的高级代码。
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Web.Scotty
main :: IO ()
main = scotty 3000 $
get "/" $ do
name <- param "name" `rescue` (\_ -> return "haskell")
greeting <- hello name
html $ concat ["<h1>hello ", greeting, "</h1>"]
hello :: String -> String
hello s = "hello " ++ s
错误信息
app/Main.hs:11:17: error:
• Couldn't match type ‘[]’
with ‘Web.Scotty.Internal.Types.ActionT
Data.Text.Internal.Lazy.Text IO’
Expected type: Web.Scotty.Internal.Types.ActionT
Data.Text.Internal.Lazy.Text IO Char
Actual type: String
<Omitted>
|
11 | greeting <- hello name
| ^^^^^^^^^^
app/Main.hs:12:12: error:
• Couldn't match expected type ‘Data.Text.Internal.Lazy.Text’
with actual type ‘[Char]’
<Omitted>
|
12 | html $ concat ["<h1>hello ", greeting, "</h1>"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
app/Main.hs:12:34: error:
• Couldn't match expected type ‘[Char]’ with actual type ‘Char’
<Omitted>
|
12 | html $ concat ["<h1>hello ", greeting, "</h1>"]
| ^^^^^^^^
目标
hello
函数是一个存根。我想证明以下机制有效。
将参数提取为字符串
应用于String -> String
函数
return响应结果
我阅读并尝试过什么
我读过 Scotty doc and some code examples。
我读到 param
是 Parsable a => Text -> ActionM a
类型,ActionM
是 ActionT Text IO
类型。
我已经尝试了 name :: T.Text <- param "name"
、T.unpack
、liftIO
等,但没有成功。我想我没有完全理解这些类型。
问题
param
和 ActionM
的类型到底是什么意思?
如何将参数提取为字符串以用于其他函数?
谢谢。
首先,一些工作代码:
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Data.Text.Lazy (Text)
import Web.Scotty
main :: IO ()
main = scotty 3000 $
get "/" $ do
name <- param "name" `rescue` (\_ -> return "haskell")
let greeting = hello name
html $ mconcat ["<h1>hello ", greeting, "</h1>"]
hello :: Text -> Text
hello s = "hello " <> s
因为 hello
不在 ActionM
monad 中,所以可以使用 let
绑定来代替 <-
语法。
param
可用于解析 Parseable
类型 class 的任何查询参数。
param :: Parsable a => Text -> ActionM a
表示给定参数的文本名称,param
可以返回任何你需要的类型,只要是Parseable
。检查 the docs 以获取可用类型列表。请注意 String
不在该列表中,但 Text
是。这就是为什么在上面的代码中我更改了 hello
函数以使用 Text
而不是 String
。如果您更喜欢使用 String
,您可以像这样解压已解析的参数:
name <- T.unpack <$> param "name" `rescue` (\_ -> return "haskell")
let greeting = hello name -- where `hello :: String -> String`
(但是在使用 html
函数之前,您需要将结果重新打包成文本)
需要进行的其他更改是将 concat
替换为 mconcat
,将 ++
替换为 <>
。这些函数完成与 concat
和 ++
相同的事情,但是更通用并且适用于所有幺半群而不仅仅是列表。
关于 ActionM
类型的最后一个问题。
在幕后,ActionM
是 ActionT
的特殊形式:ActionM = ActionT Text IO
ActionT
表示在环境(http 请求)中发生的计算,可以修改内部状态(http 响应),并可能导致错误。它是使用一堆 monad 转换器制作的,如下所示:
newtype ActionT e m a = ActionT
{ runAM :: ExceptT (ActionError e) (ReaderT ActionEnv (StateT ScottyResponse m)) a }
我是 Haskell 的新手,正在使用 Scotty 网络库测试一些概念。
但是,我无法使简单的 hello world 页面正常工作。 我坚持将参数转换为字符串并应用于另一个函数。
这是尚未运行的高级代码。
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Web.Scotty
main :: IO ()
main = scotty 3000 $
get "/" $ do
name <- param "name" `rescue` (\_ -> return "haskell")
greeting <- hello name
html $ concat ["<h1>hello ", greeting, "</h1>"]
hello :: String -> String
hello s = "hello " ++ s
错误信息
app/Main.hs:11:17: error:
• Couldn't match type ‘[]’
with ‘Web.Scotty.Internal.Types.ActionT
Data.Text.Internal.Lazy.Text IO’
Expected type: Web.Scotty.Internal.Types.ActionT
Data.Text.Internal.Lazy.Text IO Char
Actual type: String
<Omitted>
|
11 | greeting <- hello name
| ^^^^^^^^^^
app/Main.hs:12:12: error:
• Couldn't match expected type ‘Data.Text.Internal.Lazy.Text’
with actual type ‘[Char]’
<Omitted>
|
12 | html $ concat ["<h1>hello ", greeting, "</h1>"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
app/Main.hs:12:34: error:
• Couldn't match expected type ‘[Char]’ with actual type ‘Char’
<Omitted>
|
12 | html $ concat ["<h1>hello ", greeting, "</h1>"]
| ^^^^^^^^
目标
hello
函数是一个存根。我想证明以下机制有效。
将参数提取为字符串
应用于
String -> String
函数return响应结果
我阅读并尝试过什么
我读过 Scotty doc and some code examples。
我读到 param
是 Parsable a => Text -> ActionM a
类型,ActionM
是 ActionT Text IO
类型。
我已经尝试了 name :: T.Text <- param "name"
、T.unpack
、liftIO
等,但没有成功。我想我没有完全理解这些类型。
问题
param
和 ActionM
的类型到底是什么意思?
如何将参数提取为字符串以用于其他函数?
谢谢。
首先,一些工作代码:
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Data.Text.Lazy (Text)
import Web.Scotty
main :: IO ()
main = scotty 3000 $
get "/" $ do
name <- param "name" `rescue` (\_ -> return "haskell")
let greeting = hello name
html $ mconcat ["<h1>hello ", greeting, "</h1>"]
hello :: Text -> Text
hello s = "hello " <> s
因为 hello
不在 ActionM
monad 中,所以可以使用 let
绑定来代替 <-
语法。
param
可用于解析 Parseable
类型 class 的任何查询参数。
param :: Parsable a => Text -> ActionM a
表示给定参数的文本名称,param
可以返回任何你需要的类型,只要是Parseable
。检查 the docs 以获取可用类型列表。请注意 String
不在该列表中,但 Text
是。这就是为什么在上面的代码中我更改了 hello
函数以使用 Text
而不是 String
。如果您更喜欢使用 String
,您可以像这样解压已解析的参数:
name <- T.unpack <$> param "name" `rescue` (\_ -> return "haskell")
let greeting = hello name -- where `hello :: String -> String`
(但是在使用 html
函数之前,您需要将结果重新打包成文本)
需要进行的其他更改是将 concat
替换为 mconcat
,将 ++
替换为 <>
。这些函数完成与 concat
和 ++
相同的事情,但是更通用并且适用于所有幺半群而不仅仅是列表。
关于 ActionM
类型的最后一个问题。
在幕后,ActionM
是 ActionT
的特殊形式:ActionM = ActionT Text IO
ActionT
表示在环境(http 请求)中发生的计算,可以修改内部状态(http 响应),并可能导致错误。它是使用一堆 monad 转换器制作的,如下所示:
newtype ActionT e m a = ActionT
{ runAM :: ExceptT (ActionError e) (ReaderT ActionEnv (StateT ScottyResponse m)) a }