Reputation: 1328
I currently have this bit of code:
function string keys = map (xor 1) (map ord string)
Which takes every element from the string and xor's it with 1. I would like to make the map function more advanced, by replacing 1 with any element from keys.
So for example if string == "Test"
and keys = [1,3,6,9]
I would get:
'T' xor 1
'e' xor 3
's' xor 6
't' xor 9
Is there a way to iterate over all element of keys so that I can achieve this? I'm pretty new to Haskell and I don't have a good grasp of its concepts.
My attempt at solving this was:
function string keys = map (iterate xor keys) (map ord string)
but I got a few errors and I guess it's because of the iterate function.
Any help would be greatly appreciated!
Just as I posted I noticed that iterate does a completely different thing so at this point I know why it doesn't work but I don't know how to replace it.
Upvotes: 0
Views: 778
Reputation: 71065
That's what the ZipList
instance of type class Applicative
is doing:
> getZipList $ xor . ord <$> ZipList "Test" <*> ZipList [1,3,6,9, 11]
[85,102,117,125]
The get/ZipList
s serve as kind of markers to signal our intent to zip, instead of the regular list's cross-product behaviour. We're supposed to pretend--"ignore" them, reading it in our minds instead as
-- zipWith ( xor . ord ) "Test" [1,3,6,9, 11]
which is the same as
-- zipWith xor (map ord "Test" ) [1,3,6,9, 11]
-- zipWith ($) (map (xor . ord) "Test" ) [1,3,6,9, 11]
-- map (uncurry ($)) (zip (map (xor . ord) "Test" ) [1,3,6,9, 11] )
-- map (\(a,b)-> xor (ord a) b) (zip "Test" [1,3,6,9, 11] )
<$>
is a synonym for fmap
which is a synonym for map
, and <*>
is "apply".
Without the ZipList
marker, we get
> [ord] <*> "Test"
[84,101,115,116]
-- ord <$> "Test"
-- map ord "Test"
Specifically, your code should be tweaked a little bit into
function :: [Char] -> [Int] -> [Int]
-- function string keys = map (iterate xor keys) (map ord string)
function string keys = zipWith ($) (map xor keys) (map ord string)
-- = getZipList $ (xor <$> ZipList keys) <*> (ord <$> ZipList string)
($)
is an application operator, ($) f x = f $ x = f x
.
Upvotes: 0
Reputation: 101959
You want to associate one element of a list with one element of the other list.
This is often called zipping. The zipWith
seems to do exactly what you want:
Prelude Data.Bits> zipWith xor [1, 3, 5] [10, 23, 44]
[11,20,41]
It takes an a -> b -> c
function, an [a]
list and a [b]
list and apply the function element wise with corresponding elements from the two lists.
It is a generalization of the zip
function that produces pairs of element (zip = zipWith (,)
).
Upvotes: 6