为什么我不能在Yesod中从Handler返回ByteString?

Max*_*iel 5 haskell bytestring yesod

我正试图ByteStringHandlerYesod的函数中返回一个:

getHomeR :: Handler ByteString
getHomeR = return "foo"
Run Code Online (Sandbox Code Playgroud)

但我收到这个错误:

/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 }
Run Code Online (Sandbox Code Playgroud)

为什么会这样,为什么不ByteString有一个ToTypedContent实例?

Max*_*iel 9

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

问题ByteString在于它描述了任何二进制数据 - 你ByteString可能是PNG,JPEG或任何东西,因此不清楚提供它的内容类型.

如果您真的只想返回二进制数据,则octet-stream内容类型是合适的:

getHomeR :: Handler TypedContent
getHomeR = return $ TypedContent typeOctet $ toContent ("x" :: ByteString)
Run Code Online (Sandbox Code Playgroud)

但是如果可能的话,你应该尝试更好的内容类型(例如image/jpegJPEG).

在这种情况下,您可以使用TypedContent手动如上,或者自己写的实例ToTypedContent为NEWTYPE过ByteString

newtype Jpeg = Jpeg ByteString deriving (Show, ToContent)

instance ToTypedContent Jpeg where
    toTypedContent h = TypedContent "image/jpeg" (toContent h)
Run Code Online (Sandbox Code Playgroud)