1

我有一些代码(生成 Rijndael S-box,为了好玩),如下所示:

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

这看起来有点傻——这不是弃牌的完美情况吗?但我不能使用折叠,因为移动距离shiftL需要Int,当然也xor需要Bits.

对我来说,一个要操作的函数Bits不会接受Bits它的所有参数,这对我来说似乎很尴尬。我很想知道这样做的合理性,但我更想知道是否有任何优雅的方式来实现我想要的折叠。

4

2 回答 2

3

foldl :: (b -> a -> b) -> b -> [a] -> b迭代地将一个以 a 开头的函数应用于sb的列表,a直到列表用完,然后返回结果。在这种情况下,我们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的二进制等价物。

于 2017-05-08T18:25:34.393 回答
0

乔恩·珀迪(Jon Purdy)推断出我应该清楚地说明的内容-我想要一个无点函数传递给折叠,他提供了一个:liftA2 (.) xor shiftL.

于 2017-05-11T14:38:23.550 回答