2017-05-08 100 views
1

我有一些代码(生成Rijndael算法的S-box,为了好玩),看起来像这样:如何在使用xor的折叠中解决Haskell的Int shift参数?

q0 = q ⊕ shiftL q 1 
q1 = q0 ⊕ shiftL q0 2 
q2 = q1 ⊕ shiftL q1 4 

这似乎有点傻 - 不会是一个折叠的完美情况?但我不能使用折叠,因为shiftL需要一个Int的距离转移,当然xor要求Bits

对我来说,一个意图在Bits上运行的函数不会接受Bits的所有论点似乎很尴尬。我很好奇听到这种理性,但我更渴望知道是否有任何优雅的方式来实现我想要的弃牌。

+0

你在找什么结果?只有'q2',或者所有'qi's? –

+0

我只需要q2。 – sacheie

+3

我不确定我是否明白您发布的代码存在什么问题。你是否尝试使用'1','2','4'作为移位量?因为你写的东西可以翻译成简单的左边折叠,不是吗? ''sbox q = foldl'(\ q'i - > q''xor' shiftL q'i)q [1,2,4]'' –

回答

0

乔恩·珀迪推断我应该已明确表示二进制等效 - 我想要一个自由点功能来传递折叠,他提供了一个:liftA2 (.) xor shiftL

3

foldl :: (b -> a -> b) -> b -> [a] -> b迭代地将以b开头的函数应用到列表a s,直到列表耗尽并返回结果。在这种情况下,我们的a s可以是移位长度。所以1,2,4。我们可以用iterate :: (a -> a) -> a -> [a]构建这样一个列表。确实:

powers2 = iterate (2*) 1 

现在我们可以将该列表提供给foldl。功能foldl执行的是\qi s -> xor qi (shiftL qi s)。因此,完整的职能将是:

qn :: (Num a, Foldable t, Bits [a]) => Int -> r -> t Int -> [a] 
qn n q = foldl (\qi s -> xor qi (shiftL qi s)) q $ take n $ iterate (2*) 1 

所以如果我们调用qn 3 q我们对q执行功能的三倍,从而获得您的示例q2。例如:

Prelude Data.Bits> qn 3 15 
1285 

由于:

q   = 0000 0000 1111 
shiftL q 1 = 0000 0001 1110 
       -------------- 
q0   = 0000 0001 0001 
shiftL q0 2 = 0000 0100 0100 
       -------------- 
q1   = 0000 0101 0101 
shiftL q1 4 = 0101 0101 0000 
       -------------- 
q2   = 0101 0000 0101 

这是1285