Ошибка типа, связанная с Word8 и Int

#haskell

#haskell

Вопрос:

Попытка преобразовать байтовую строку в отображение шестнадцатеричной строки ascii

 wordtoascii :: Int -> String
wordtoascii y =
  showIntAtBase 16 intToDigit ( fromEnum  y) ""

bs2string :: Data.ByteString.ByteString -> String
bs2string bs = do
  Prelude.map( wordtoascii,
               (unpack bs))
  

Ошибка типа:

 Couldn't match expected type `a -> b'
       against inferred type `(Int -> String, [GHC.Word.Word8])'
In the first argument of `Prelude.map', namely
    `(wordtoascii, (unpack bs))'
In the expression: Prelude.map (wordtoascii, (unpack bs))
In the expression: do { Prelude.map (wordtoascii, (unpack bs)) }
  

Ответ №1:

Это не тот синтаксис, который вы думаете.

 Prelude.map( wordtoascii,
            (unpack bs))
  

Это то же самое, что:

 let x = (wordtoascii, unpack bs)
in map x
  

Удалите круглые скобки и запятую.

 map wordtoascii (unpack bs)
  

Однако это также неверно. Поскольку тип приведенного выше выражения [String] , нет String . Вы хотите concatMap , что похоже map , но объединяет результаты в одну строку.

 concatMap wordtoascii (unpack bs)
  

Или, еще лучше,

 bs2string = concatMap wordtoascii . unpack
  

Запятая предназначена для создания кортежей, списков и записей. Например, (1, 7) :: (Int, Int) могут быть декартовы координаты. Запятая не отображается при вызовах функций.

Обычно ByteString импортируется только как квалифицированный импорт, поскольку так много функций конфликтуют Prelude . Это устраняет необходимость в Prelude. квалификации функций, которые конфликтуют.

 import qualified Data.ByteString as S
bs2string = map wordtoascii . S.unpack
  

S Расшифровывается как Strict . BS также является распространенным выбором, он расшифровывается как for Bytestring (строгий).

Комментарии:

1. Интересно… После того, как я исправлю это, я все равно получаю ошибку преобразования как «Не удалось сопоставить ожидаемый Int с введенным типом GHC.Word.Word8».

2. Ну, тогда используйте (wordtoascii . fromIntegral) вместо wordtoascii . fromIntegral Функция очень, очень удобная. Он также довольно хорошо оптимизирован.

Ответ №2:

Дитрих объяснил основную проблему с вашим кодом. Однако существует также проблема, которая unpack возвращает список Word8 ожидаемых и ожидаемых вашим кодом Int . Это можно исправить, просто ослабив сигнатуру типа wordtoascii :

 > let wordtoascii y = showIntAtBase 16 intToDigit ( fromEnum  y) ""
> :t wordtoascii
wordtoascii :: Enum a => a -> String
  

Word8 является экземпляром Enum , поэтому с сигнатурой этого типа вы можете использовать ее напрямую.