0

我正在实现一些加密功能,因此,为了节省一些时间,我编写了一个模块,用于在 、 和 之间转换八位位组( Word8) 。如何改进我的代码?我确信现有的 Haskell 模块包含可以缩短我的代码的函数。我跑过去了。[Octet]ByteStringUArray Int Octethlint

{-# LANGUAGE FlexibleInstances #-}

module Octets where

import Codec.Utils (Octet)
import Data.Array.IArray (elems, listArray)
import Data.Array.Unboxed (UArray)
import qualified Data.ByteString as B (ByteString, length, pack, unpack)

class FromByteString a where
  fromByteString :: B.ByteString -> a

instance FromByteString [Octet] where
  fromByteString = B.unpack

instance FromByteString (UArray Int Octet) where
  fromByteString bytes = listArray (0, B.length bytes - 1) $ B.unpack bytes

class FromOctets a where
  fromOctets :: [Octet] -> a

instance FromOctets B.ByteString where
  fromOctets = B.pack

instance FromOctets (UArray Int Octet) where
  fromOctets bytes = listArray (0, length bytes - 1) bytes

class FromUArray a where
  fromUArray :: UArray Int Octet -> a

instance FromUArray B.ByteString where
  fromUArray = B.pack . elems

instance FromUArray [Octet] where
  fromUArray = elems

这是测试套件:

{-# LANGUAGE OverloadedStrings #-}

module OctetsSpec where

import Codec.Utils (Octet)
import Data.Array.IArray (listArray)
import Data.Array.Unboxed (UArray)
import qualified Data.ByteString as B (ByteString, length, unpack)
import Octets
import Test.Hspec (describe, hspec, it, shouldBe, Spec)

main :: IO ()
main = hspec spec

spec :: Spec
spec = specOctets

specOctets :: Spec
specOctets = do
  describe "FromByteString" $ do
    it "should convert ByteString to [Octet]" $ do
      let result = fromByteString "foobar" :: [Octet]
      result `shouldBe` [102, 111, 111, 98, 97, 114]

    it "should convert ByteString to (UArray Int Octet)" $ do
      let testString = "foobar"
          result = fromByteString testString :: UArray Int Octet
      result `shouldBe`
        (listArray (0, B.length testString - 1) $ B.unpack testString)

  describe "FromOctets" $ do
    it "should convert [Octet] to ByteString" $ do
      let result = fromOctets [102, 111, 111, 98, 97, 114] :: B.ByteString
      result `shouldBe` "foobar"

    it "should convert [Octet] to (UArray Int Octet)" $ do
      let testList = [102, 111, 111, 98, 97, 114]
          result = fromOctets testList :: (UArray Int Octet)
      result `shouldBe` (listArray (0, length testList - 1) testList)

  describe "FromUArray" $ do
    it "should convert (UArray Int Octet) to ByteString" $ do
      let testList = [102, 111, 111, 98, 97, 114]
          result = (fromUArray $
            listArray (0, length testList - 1) testList) :: B.ByteString
      result `shouldBe` "foobar"

    it "should convert (UArray Int Octet) to [Octet]" $ do
      let testList = [102, 111, 111, 98, 97, 114]
          result = (fromUArray $
            listArray (0, length testList - 1) testList) :: [Octet]
      result `shouldBe` testList
4

1 回答 1

2

这是我最喜欢的用途之一,lens它提供了Iso类型。由于您有 3 个示例,因此您可以声明它们彼此都具有3 choose 2 = 3同构同构。

byteStringOctets :: Iso' ByteString [Octet]
uarrayOctets     :: Iso' (UArray Int Octet) [Octet]
byteStringUArray :: Iso' ByteString (UArray Int Octet)

由于这些很常见Iso',它们也已经存在。特别是如果您愿意使用vector包而不是array.

byteStringOctets = from packedBytes  -- from Data.ByteString.Lens
                                     -- works with lazy and strict ByteStrings

vectorOctets :: Iso' (Vector Octet) [Octet]
vectorOctets = from vector           -- from Data.Vector.Lens

byteStringVector :: Iso' ByteString Vector

wherebyteStringVector可以通过将这些当前的同构粘合在一起(效率低下)或通过稍微限制类型并按照 Stack Overflow 问题描述的那样进行直接转换来实现。

于 2013-09-14T18:51:53.580 回答