Reputation: 113
I got problems with turning ByteString's into Text and vice versa. Here's the code:
{-# LANGUAGE OverloadedStrings #-}
import Web.Scotty
import Web.ClientSession
import Data.Text.Lazy (Text, toStrict, fromStrict)
import Data.Text.Lazy.Encoding (encodeUtf8, decodeUtf8)
import Data.ByteString (ByteString)
import Data.Monoid ((<>))
initCookies :: IO (Text -> ActionM ())
initCookies = do
key <- getDefaultKey
return $ setCookie key
where
setCookie k id = encryptIO k (encode id)
>>= (\x -> header "Set-Cookie" ("sid=" <> decode x <> ";"))
encode :: Text -> ByteString
encode = encodeUtf8 . toStrict
decode :: ByteString -> Text
decode = fromStrict . decodeUtf8
and error message:
foo.hs:16:35:
Couldn't match expected type `bytestring-0.10.0.2:Data.ByteString.Internal.ByteString'
with actual type `ByteString'
In the return type of a call of `encode'
In the second argument of `encryptIO', namely `(encode id)'
In the first argument of `(>>=)', namely `encryptIO k (encode id)'
foo.hs:17:18:
Couldn't match type `ActionM' with `IO'
Expected type: IO ()
Actual type: ActionM ()
In the return type of a call of `header'
In the expression: header "Set-Cookie" ("sid=" <> decode x <> ";")
In the second argument of `(>>=)', namely
`(\ x -> header "Set-Cookie" ("sid=" <> decode x <> ";"))'
foo.hs:17:56:
Couldn't match expected type `ByteString'
with actual type `bytestring-0.10.0.2:Data.ByteString.Internal.ByteString'
In the first argument of `decode', namely `x'
In the first argument of `(<>)', namely `decode x'
In the second argument of `(<>)', namely `decode x <> ";"'
So, my guess this error has something to do with what ClientSession actually use, in their source code they seem to use normal bytestring which should work with my implementation. Look here:
[..]
import qualified Data.ByteString as S
[..]
encryptIO :: Key -> S.ByteString -> IO S.ByteString
[..]
So why do I get all these errors? Thanks.
Upvotes: 4
Views: 3749
Reputation: 1008
The Data.String.Conversions
package abstracts that knowledge with a single cs
conversion function, which version is called depending on the context of the call (i.e. input and expected type).
Upvotes: 2
Reputation: 4637
You were mixing Data.ByteString.ByteString
and Data.ByteString.Lazy.ByteString
. Because the type names are equal GHC can (and does) produce terrible error messages. I reworked it using explicit imports for ByteString
and Text
, hopefully it's a little more obvious now:
{-# LANGUAGE OverloadedStrings #-}
import Web.Scotty
import Web.ClientSession
import Control.Monad.Trans (liftIO)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Encoding as TL
import qualified Data.ByteString as B
import qualified Data.ByteString as BL
import Data.Monoid ((<>))
initCookies :: IO (TL.Text -> ActionM ())
initCookies = do
key <- getDefaultKey
return $ setCookie key
where
setCookie k id = liftIO (encryptIO k (encode id))
>>= (\x -> header "Set-Cookie" ("sid=" <> decode x <> ";"))
encode :: TL.Text -> B.ByteString
encode = T.encodeUtf8 . TL.toStrict
decode :: B.ByteString -> TL.Text
decode = TL.fromStrict . T.decodeUtf8
Upvotes: 10