ByteString в отложенный текст и наоборот

У меня проблемы с превращением ByteString в текст и наоборот. Вот код:

{-# 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

и сообщение об ошибке:

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 <> ";"'

Итак, я предполагаю, что эта ошибка имеет какое-то отношение к тому, что на самом деле использует ClientSession, в своем исходном коде они, похоже, используют обычную байтовую строку, которая должна работать с моей реализацией. Смотри сюда:

[..]
import qualified Data.ByteString as S
[..]
encryptIO :: Key -> S.ByteString -> IO S.ByteString
[..]

Так почему я получаю все эти ошибки? Спасибо.


person klrr    schedule 12.09.2013    source источник
comment
У вас установлено несколько версий байтовой строки?   -  person bennofs    schedule 12.09.2013
comment
Нет, насколько мне известно, только bytestring-0.10.2.0. Может быть, Web.ClientSession использует другой?   -  person klrr    schedule 12.09.2013
comment
Когда ghc сообщение об ошибке содержит полностью определенный тип с именем пакета, например bytestring-0.10.0.2:Data.ByteString.Internal.ByteString, то на 99% ваш пакет косвенно зависит от двух разных версий пакета. Предположение @bennofs, скорее всего, верное. Опубликовать вывод ghc-pkg list bytestring   -  person Yuras    schedule 12.09.2013
comment
Например. см. stackoverflow.com/questions/12576817/   -  person Yuras    schedule 12.09.2013
comment
Да, это была проблема, спасибо!   -  person klrr    schedule 12.09.2013


Ответы (2)


Вы смешивали Data.ByteString.ByteString и Data.ByteString.Lazy.ByteString. Поскольку имена типов совпадают, GHC может (и делает) выдавать ужасные сообщения об ошибках. Я переработал его, используя явный импорт для ByteString и Text, надеюсь, теперь это немного более очевидно:

{-# 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
person Nathan Howell    schedule 12.09.2013
comment
Фрагмент импортирует только Data.ByteString. И ошибка жалуется на ByteString и bytestring-0.10.0.2:Data.ByteString.Internal.ByteString, оба являются строгими байтовыми строками. Ленивый объявлен в Data.ByteString.Lazy.Internal.ByteString. Что я пропустил? - person Yuras; 12.09.2013
comment
@Yuras: Модуль Data.Text.Lazy.Encoding имеет дело с Data.ByteString.Lazy.ByteStrings не строгими, однако сообщение об ошибке вводит в заблуждение. - person Nathan Howell; 12.09.2013
comment
Вы имеете в виду ошибку типа в encode и decode. Но у автора есть ошибка в initCookies (foo.hs: 16: 35), которая определенно касается разных bytestring версий. Когда он исправит эту проблему, он также получит сообщение об ошибке, о которой вы говорите. Я не говорю, что вы ошибаетесь, но исходная проблема связана с адом зависимостей. - person Yuras; 12.09.2013
comment
@Yuras, кажется, ты прав, но он все равно не скомпилировался: ^) - person Nathan Howell; 12.09.2013

Пакет Data.String.Conversions абстрагируется от этого знаний с помощью одной cs функции преобразования, версия которой вызывается в зависимости от контекста вызова (т. е. ввода и ожидаемого типа).

person Titou    schedule 12.12.2014