2017-05-08 99 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