为什么我不能 return 来自 Yesod 处理程序的 ByteString?

Why can't I return a ByteString from a Handler in Yesod?

我正在尝试从我在 Yesod 中的 Handler 函数 return ByteString

getHomeR :: Handler ByteString
getHomeR = return "foo"

但我收到此错误:

/Users/maximiliantagher/Documents/Mercury/hs/mercury-web-backend/src/Application.hs:48:1: error:
    • No instance for (ToTypedContent ByteString)
        arising from a use of ‘yesodRunner’
    • In the expression:
        yesodRunner getHomeR env1404_axwe (Just HomeR) req1404_axwf
      In a case alternative:
          "GET"
            -> yesodRunner getHomeR env1404_axwe (Just HomeR) req1404_axwf
      In the expression:
        case Network.Wai.Internal.requestMethod req1404_axwf of {
          "GET"
            -> yesodRunner getHomeR env1404_axwe (Just HomeR) req1404_axwf
          _ -> yesodRunner
                 (void badMethod) env1404_axwe (Just HomeR) req1404_axwf }

为什么会这样,为什么 ByteString 没有 ToTypedContent 实例?

ToTypedContentclass描述了content-type是什么数据。因此,具有关联内容类型的类型(例如 TextValue (JSON) 的 UTF 8)可以具有自然的 ToTypedContent 实例。

ByteString 的问题在于它描述了任何二进制数据——您的 ByteString 可能是 PNG、JPEG 或任何其他格式,因此不清楚要赋予它什么内容类型。

如果你真的只想return二进制数据,octet-stream内容类型是合适的:

getHomeR :: Handler TypedContent
getHomeR = return $ TypedContent typeOctet $ toContent ("x" :: ByteString)

但如果可能,您应该尝试使用更好的内容类型(例如 image/jpeg 用于 JPEG)。

在这种情况下,您可以像上面那样手动使用 TypedContent,或者为 ByteString

上的新类型编写您自己的 ToTypedContent 实例
newtype Jpeg = Jpeg ByteString deriving (Show, ToContent)

instance ToTypedContent Jpeg where
    toTypedContent h = TypedContent "image/jpeg" (toContent h)