Если производительность не критична, я бы рекомендовал использовать битовое векторное представление для такого проекта.Как вы обнаружили, случайный доступ к отдельным битам является чем-то вроде боли, когда они находятся в упакованном виде, но Data.Vector
предоставляет множество функций для такого рода задач.
import Data.Bits
import qualified Data.Vector as V
type BitVector = V.Vector Bool
unpack :: (Bits a) => a -> BitVector
unpack w = V.generate (bitSize w) (testBit w)
pack :: (Bits a) => BitVector -> a
pack v = V.ifoldl' set 0 v
where
set w i True = w `setBit` i
set w _ _ = w
mkPermutationVector :: Int -> V.Vector Int
mkPermutationVector d = V.generate (2^d) b
where
b i | i < 2^(d-1) = 2*i
| otherwise = let i' = i-2^(d-1)
in 2*i'+1
permute :: Int -> BitVector -> BitVector
permute d v = V.backpermute v (mkPermutationVector d)
Обратите внимание, как это позволяет вам задавать перестановку путем точной расшифровки математического описания.Это существенно снижает вероятность ошибок и является более приятным для написания, чем битовый код.
Чтобы проверить с помощью вашего примера вектора (в базе 10):
*Main> import Data.Word
*Main Data.Word> let permute16 = pack . permute 4 . unpack :: Word16 -> Word16
*Main Data.Word> permute16 43690
65280
ТеперьПереходя к битовым векторам в качестве вашего представления, вы теряете много того, что получаете бесплатно, используя типы Haskell, такие как Num
экземпляры.Тем не менее, вы всегда можете реализовать операции Num
для своего представления;Вот начало:
plus :: BitVector -> BitVector -> BitVector
plus as bs = V.tail sums
where
(sums, carries) = V.unzip sumsAndCarries
sumsAndCarries = V.scanl' fullAdd (False, False) (V.zip as bs)
fullAdd (_, cin) (a, b) = ((a /= b) /= cin
, (a && b) || (cin && (a /= b)))
Вы также можете найти полезным пакет Левента Эркока sbv
, хотя я не уверен, что он предоставляет такую удобную функцию, как backpermute
для вашего конкретного случая.вопрос.
Обновление : я подумал, что на этот вопрос интересно ответить, поэтому я выбрал код в виде библиотеки: bit-vector .