【发布时间】:2021-04-14 20:31:52
【问题描述】:
我正在尝试学习 Haskell,我想我会尝试复制 Linux 'xxd' 实用程序。但是我被困在右侧列(显示 ASCII 或非打印字符的空白)。
提醒一下,典型的 xxd 输出如下所示:
00000000: 4927 6d20 7472 7969 6e67 2074 6f20 6c65 I'm trying to le
00000010: 6172 6e20 4861 736b 656c 6c2e 2041 7320 arn Haskell. As
...
我还想利用 Unicode“控制图片”块来显示控制代码 0..31 的小符号,而不是点或占位符。所以我有一个辅助函数,可以将 Word8 转换为 Char,同时用控制图片块中的等效字符替换控制字符。
http://www.unicode-symbol.com/block/Control_Pictures.html
约束:最终程序将从磁盘读取文件,因此我希望读取 ByteString 或惰性 ByteString。我也想使用 Data.Text 来保存输出而不是 String。
理想情况下:我想避免将 ByteString 转换为其他批发形式,例如[Word8] 因为 - 最终 - 我需要学习如何使用它,而不是绕过它。
我的问题是我无法让map 为我工作。 B.map 和 T.map 都不起作用,因为它们需要一个函数 ([a] -> [a])。 Prelude.map 看起来更有希望,因为它期望 ([a] -> [b]) 但我无法让它与导入的类型一起使用。所以我尝试定义自己的map(只是为了尝试找到可以工作的东西,然后当我有更好的理解时,我可以用内置函数替换)但这也不起作用。
我的非功能代码如下
import qualified Data.ByteString as B
import qualified Data.Text as T
import Data.Word
import Data.Char
{- Make some normally undisplayable bytes into displayable chars -}
displayableChar :: Word8 -> Char
displayableChar w
| i < 32 = chr (0x2400 + i) -- 0x2420 control codes
| i < 33 = chr 0x2423 -- 0x2423 trough for space
| i < 127 = chr i
| i < 128 = chr 0x2421 -- 0x2421 del
| otherwise = ' '
where i = fromIntegral w
mymap :: (Word8 -> Char) -> B.ByteString -> [Char]
mymap f bstr
| bstr == B.empty = []
| otherwise = f x : map f xs
where
x = B.head bstr
xs = B.tail bstr
test_data = B.pack [1..250]
欢迎提出建议和建议,了解将displayableChar 应用于 ByeString 中的每个字节并输出文本的“正确”方式。
【问题讨论】:
标签: haskell