2016-04-10 2 views
0

я в настоящее время этот бит кода:Применить карту, используя другую функцию к каждому элементу списка

function string keys = map (xor 1) (map ord string) 

Который берет каждый элемент из строки и XOR вот именно с 1. я хотел бы сделать map более продвинутый, заменив 1 на любой элемент из ключей.

Так, например, если string == "Test" и keys = [1,3,6,9] я хотел бы получить:

'T' xor 1 
'e' xor 3 
's' xor 6 
't' xor 9 

Есть ли способ для перебора всех элементов ключей, так что я могу добиться этого? Я довольно новичок в Haskell, и у меня нет хорошего понимания его концепций.

Моя попытка решить это:

function string keys = map (iterate xor keys) (map ord string) 

, но я получил несколько ошибок, и я предполагаю, что это из-за функции итерации.

Любая помощь была бы принята с благодарностью!


Так же, как я писал, я заметил, что итерация делает совершенно другую вещь, поэтому на данный момент я знаю, почему это не работает, но я не знаю, как заменить его.

ответ

6

Вы хотите связать один элемент списка с одним элементом другого списка. Это часто называют zipping. zipWith, кажется, делает именно то, что вы хотите:

Prelude Data.Bits> zipWith xor [1, 3, 5] [10, 23, 44] 
[11,20,41] 

Он принимает a -> b -> c функцию, в [a] список и [b] список и применить функцию поэлементно с соответствующими элементами из двух списков.

Это обобщение функции zip, которая создает пары элементов (zip = zipWith (,)).

+0

Большое вам спасибо, именно то, что я искал! Есть ли хорошее место, где я могу найти аналогичные функции, которые я мог бы изучить? Не обязательно функции, которые делают то же самое, но полезны для новичков. – Xzenon

+2

@ Xzenon Вы можете использовать [hoogle] (https://www.haskell.org/hoogle/) для поиска функций по имени или типу. Например, в вашем случае вам нужно что-то с типом '(a -> a -> a) -> [a] -> [a] -> [a]', поиск объекта производит [эти результаты] (https: // www.haskell.org/hoogle/?hoogle=%28a+-%3E+a+-%3E+a%29+-%3E+[a]+-%3E+[a]+-%3E+[a]), и вы можете см. 'zipWith' тоже среди них. Также вы должны проверить модуль 'Prelude', чтобы увидеть наиболее полезные функции. – Bakuriu

+0

'Data.List' - еще одно хорошее место для поиска. – dfeuer

0

Вот что ZipList экземпляр типа класса Applicative делает:

> getZipList $ xor  . ord <$> ZipList "Test" <*> ZipList [1,3,6,9, 11] 
[85,102,117,125] 

В get/ZipList s служат своего рода маркерами, чтобы сигнализировать наше намерение к молнии, а поведение кросс-продукта регулярного списка. Мы должны притворяться - «игнорировать» их, читая его в нашем сознании, а не в качестве

-- zipWith (xor  . ord)   "Test"    [1,3,6,9, 11] 

, который так же, как

-- 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]) 

<$> является синонимом fmap, который является синонимом map, и <*> «применяется».

Без ZipList маркера, мы получаем

> [ord] <*> "Test" 
[84,101,115,116] 

--  ord <$> "Test" 
-- map ord  "Test" 

В частности, код должен быть изменен немного в

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) 

($) является оператор приложения, ($) f x = f $ x = f x.

Смежные вопросы