【发布时间】:2018-09-27 16:36:30
【问题描述】:
我遇到了 Haskell 的类型问题,下面的程序抛出编译时错误:
Couldn't match expected type ‘bytestring-0.10.8.2:Data.ByteString.Lazy.Internal.ByteString’ with actual type ‘Text’
程序是:
{-# LANGUAGE OverloadedStrings #-}
module Main where
...
import Control.Concurrent (MVar, newMVar, modifyMVar_, modifyMVar, readMVar)
import qualified Data.Text as T
import qualified Data.Text.IO as T
import qualified Network.WebSockets as WS
import Data.Map (Map)
import Data.Aeson (decode)
...
application :: MVar ServerState -> WS.ServerApp
application state pending = do
conn <- WS.acceptRequest pending
msg <- WS.receiveData conn
-- EITHER this line can be included
T.putStrLn msg
-- OR these two lines, but not both
decodedObject <- return (decode msg :: Maybe (Map String Int))
print decodedObject
...
在我看来,基本问题是putStrLn 期望Text 而decode 期望Bytetring。
我不明白为什么我可以运行这部分代码:
T.putStrLn msg
或者我可以运行这部分代码:
decodedObject <- return (decode msg :: Maybe (Map String Int))
print decodedObject
但不能同时使用。
在程序中解决此问题的正确方法是什么?
我猜这类似于类型强制、类型推断或其他语言中的强制转换。问题是我不知道如何清楚地表达这个问题来查找它。
好像msg 可以是多种类型之一,但是一旦它被强制为一种类型,就不能再成为另一种类型了......
我也不确定这是否与重载字符串重叠。我有编译指示并且正在使用-XOverloadedStrings进行编译
我是个新手,所以希望这是一个合理的问题。
感谢您的任何建议!谢谢
【问题讨论】:
-
这里没有强制转换,
WS.receiveData conn的类型在其返回类型中是多态的。 Java 中的等价物是一个泛型方法,而在 C++ 中它是一个模板。不同之处在于 Java 和 C++ 都不能推断仅用作返回类型的类型参数,因此在 Java 或 C++ 中,您必须显式编写receiveData<Text>(conn)才能获得Text或receiveData<ByteString>(conn)才能获得 @ 987654335@。 Haskell 足够聪明,可以根据您对结果的处理来推断这一点,但是如果您将其同时用作ByteString和Text,则不再适用。 -
ByteString是字节序列,Text是字符序列。仅当您知道字节确实是文本并且正在使用哪个 encoding 时,您才能将ByteString转换为Text。例如,您可以使用来自Data.Text.Encoding的decodeUtf8 :: ByteString -> Text -
谢谢@sepp2k,@chi,这真的很有帮助,我想我现在都明白了,并在我的额外答案中总结了它
标签: haskell