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を提供する私のお気に入りの使用法の 1 つです。Iso3つの例があるので、それらはすべて同型で互いに同型であると述べることができます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は、これらの現在の同形を一緒に接着する (非効率的) か、このスタック オーバーフローの質問が説明しているように、型を少し制限して直接変換を行うことで実装できます。

于 2013-09-14T18:51:53.580 に答える