I am having a type issue with Haskell, the program below throws the compile time error:
Couldn't match expected type ‘bytestring-0.10.8.2:Data.ByteString.Lazy.Internal.ByteString’ with actual type ‘Text’
Program is:
{-# 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
...
It seems to me that the basic issue is that putStrLn expects Text
whereas decode expects Bytetring
.
What I don't get is why I can run this section of the code:
T.putStrLn msg
Or I can run this section of the code:
decodedObject <- return (decode msg :: Maybe (Map String Int))
print decodedObject
But not both together.
What is the proper way to resolve this issue in the program?
I guess this is something like Type Coercion, or Type Inference, or what would be Casting in other languages. The problem is I don't know how to phrase the problem clearly enough to look it up.
It's as if msg
can be one of a number of Types, but as soon as it is forced to be one Type, it can't then be another...
I'm also not sure if this overlaps with Overloaded strings. I have the pragma and am compiling with -XOverloadedStrings
I'm quite a newbie, so hope this is a reasonable question.
Any advice gratefully received! Thanks
WS.receiveData conn
is polymorphic in its return type. The equivalent in Java would be a generic method and in C++ it'd be a template. The difference is that neither Java nor C++ can infer type arguments that are only used as the return type, so in Java or C++ you'd have to explicitly writereceiveData<Text>(conn)
to get aText
orreceiveData<ByteString>(conn)
to get aByteString
. Haskell is smart enough to infer this based on what you do with the result, but if you use it as both aByteString
and aText
, that no longer works. – sepp2kByteString
is a sequence of bytes, while aText
is a sequence of characters. You can turn aByteString
into aText
only if you know that the bytes are indeed text, and which encoding is being used. For instance, you can usedecodeUtf8 :: ByteString -> Text
fromData.Text.Encoding
– chi