将[Char]和[Word8]之间转换的最佳方法是什么?

12

我刚接触Haskell,并尝试在我的应用程序中使用纯的SHA1实现(Data.Digest.Pure.SHA),同时还使用了JSON库(AttoJSON)。

AttoJSON使用Data.ByteString.Char8字节字符串,而SHA使用Data.ByteString.Lazy字节字符串,而我的一些字符串字面值是[Char]

Haskell Prime的Char类型维基页面似乎表明这仍然是Haskell语言/Prelude中正在解决的问题。

有关Unicode支持的这篇博客文章列出了一些库,但已经有几年了。

目前最好的在这些类型之间进行转换的方法是什么,以及一些权衡有哪些?

谢谢!


http://hackage.haskell.org/packages/archive/utf8-string/0.3.7/doc/html/Data-ByteString-Lazy-UTF8.html - singpolyma
请注意,Char 无法安全地转换为 Word8,因为 Char 可以存储比 Word8 更多的值。 - singpolyma
6个回答

6

这是我的代码,没有使用ByteString的内部函数。

import Data.ByteString as S (ByteString, unpack)
import Data.ByteString.Char8 as C8 (pack)
import Data.Char (chr)

strToBS :: String -> S.ByteString
strToBS = C8.pack

bsToStr :: S.ByteString -> String
bsToStr = map (chr . fromEnum) . S.unpack

在一个ByteString上使用S.unpack会给我们[Word8],我们应用(chr . fromEnum)将任何枚举类型转换为字符。将它们全部组合在一起,就得到了我们想要的函数!

4

想要在Char8和Word8之间进行转换,您应该能够使用toEnum/fromEnum转换,因为它们表示相同的数据。

对于Char和字符串,您可能可以使用Data.ByteString.Char8.pack/unpack或某种组合的map、toEnum和fromEnum,但如果您使用除ASCII以外的任何内容,这将排除数据。

对于可能包含不仅仅是ASCII字符的字符串,一种流行的选择是UTF8编码。我喜欢用utf8-string包来实现:

http://hackage.haskell.org/packages/archive/utf8-string/0.3.6/doc/html/Codec-Binary-UTF8-String.html


2

Char8 和普通的 bytestring 是同一种东西,只是根据你导入哪个模块有不同的接口。主要情况下你需要在严格和惰性 bytestrings 之间转换,你可以使用 toChunksfromChunks

如果要将字符放到 bytestring 中,请使用 pack

请注意,如果您的字符包含 UTF-8 的多字节表示形式,则可能会出现问题。


1
注意:这只回答了一个非常特定的情况(对硬编码字符串调用函数)的问题。
这可能看起来是一个小问题,因为如先前的答案所述,存在转换函数。但我想要一种减少管理代码的方法,即你必须编写的代码才能使函数协同工作。
减少字符串类型处理代码的解决方案是使用OverloadedStrings预处理指令并导入相关模块。
{-# LANGUAGE OverloadedStrings #-}
module Dummy where
import  Data.ByteString.Lazy.Char8 (ByteString, append)

bslHandling :: ByteString -> ByteString
bslHandling = (append myWord8List)

myWord8List = "I look like a String, but I'm actually a ByteString" 

注意:编译器会推断出myWordList的类型。
  • 如果您在bslHandling中未使用它,则上述声明将生成经典的[Char]类型。

  • 这并不能解决从一个特定类型到另一个类型的问题

希望能帮到您


0

也许你想要这样做:

import Data.ByteString.Internal (unpackBytes)
import Data.ByteString.Char8 (pack)
import GHC.Word (Word8)

strToWord8s :: String -> [Word8]
strToWord8s = unpackBytes . pack 

-1
假设Char和Word8是相同的,
import Data.Word ( Word8 ) 
import Unsafe.Coerce ( unsafeCoerce ) 

toWord8 :: Char -> Word8
toWord8 = unsafeCoerce

strToWord8 :: String -> Word8
strToWord8 = map toWord8

这是一个非常糟糕的假设,因为 Haskell 支持 Unicode。 unsafeCoerce 之所以被称为 unsafe,就是因为像这样的事情。 - anon
的确,Jacob Wang的回答更好。 - penkovsky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接