如何使用 xor 在折叠中解决 Haskell 的 Int shift 参数?
How to work around Haskell's Int shift argument in a fold using xor?
我有一些代码(为了好玩而生成 Rijndael S-box)如下所示:
q0 = q ⊕ shiftL q 1
q1 = q0 ⊕ shiftL q0 2
q2 = q1 ⊕ shiftL q1 4
这似乎有点愚蠢 - 这不是弃牌的完美情况吗?但是我不能使用折叠,因为 shiftL
需要 Int
来移动距离,当然 xor
需要 Bits
.
对我来说,一个旨在对 Bits
进行操作的函数不会接受 Bits
的所有参数,这对我来说似乎很尴尬。我很想知道这样做的合理性,但我更想知道是否有任何优雅的方法来实现我想要的折叠。
foldl :: (b -> a -> b) -> b -> [a] -> b
迭代地将以 b
开头的函数应用于 a
的列表,直到列表耗尽,然后 returns 结果。在这种情况下,我们的 a
可以是 移位长度 。所以 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 的二进制等价物。
Jon Purdy 推断出我应该明确说明的内容 - 我想要一个无点函数传递给 fold,他提供了一个:liftA2 (.) xor shiftL
.
我有一些代码(为了好玩而生成 Rijndael S-box)如下所示:
q0 = q ⊕ shiftL q 1
q1 = q0 ⊕ shiftL q0 2
q2 = q1 ⊕ shiftL q1 4
这似乎有点愚蠢 - 这不是弃牌的完美情况吗?但是我不能使用折叠,因为 shiftL
需要 Int
来移动距离,当然 xor
需要 Bits
.
对我来说,一个旨在对 Bits
进行操作的函数不会接受 Bits
的所有参数,这对我来说似乎很尴尬。我很想知道这样做的合理性,但我更想知道是否有任何优雅的方法来实现我想要的折叠。
foldl :: (b -> a -> b) -> b -> [a] -> b
迭代地将以 b
开头的函数应用于 a
的列表,直到列表耗尽,然后 returns 结果。在这种情况下,我们的 a
可以是 移位长度 。所以 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 的二进制等价物。
Jon Purdy 推断出我应该明确说明的内容 - 我想要一个无点函数传递给 fold,他提供了一个:liftA2 (.) xor shiftL
.