2016-08-18 3 views
0

Я довольно новичок в Haskell, и я пытаюсь изменить список. В то же время я хочу изменить списки в этом списке. Так, например:Перемещение списка в другом списке в Haskell

Prelude> rev [[3,4,5],[7,5,2]] 
[[2,5,7],[5,4,3]] 

Я знаю, что следующий код изменяет список:

rev :: [[a]] -> [[a]] 
rev [[]] = [[]] 
rev [[x]] = [[x]] 
rev xs = last xs : reverse (init xs) 

Я изо всех сил за то время, я сделал некоторые дополнения к коду, но он по-прежнему не работает и я застрял.

rev :: [[a]] -> [[a]] 
rev [[]] = [[]] 
rev [[x]] = [[x]] 
rev xs = last xs : reverse (init xs) 
rev [xs] = last [xs] : reverse (init [xs]) 

Буду признателен за любую помощь. Заранее спасибо.

+3

Непосредственно, это просто 'rev = reverse. карта обратная' – Alec

+0

Отлично! Спасибо. – ZCoder

+0

Кстати, естественный способ написать 'reverse' путем сопоставления шаблонов - использовать вспомогательную функцию и накопительный список; сначала 'rev ls = loop [] ls' then' loop acc [] = acc; loop acc (a: as) = ​​loop (a: acc) ls' – Michael

ответ

7

Мы должны отменить внутренние списки и список выходных. Чтобы отменить внутренние списки, вы можете использовать map для применения reverse для каждого элемента списка: map reverse [[3,4,5],[7,5,2]] == [[5,4,3],[2,5,7]]. Затем просто снова измените результат reverse $ map reverse [[3,4,5],[7,5,2]] == [[2,5,7],[5,4,3]].

Функция, которая составляет только композицию reverse и map reverse, поэтому rev = reverse . map reverse.

Здесь мы сначала перевернем внутренние списки, а затем список, но порядок не имеет значения, и мы можем сделать это наоборот: rev = map reverse . reverse.

+0

Он отлично поработал! Благодарю. – ZCoder

+0

Не имеет значения, сначала вы меняете внутренние или внешние списки. – Ingo

+0

@Ingo Вы правы, это был просто удобный способ поговорить, чтобы сделать решение более ясным, а мыслительный процесс стал яснее;) Но я добавлю точность – villou24

1

Самый естественный подход, безусловно, либо map reverse . reverse, либо reverse . map reverse. Это, вероятно, наиболее эффективным, однако, чередовать операции в явном виде:

revrev :: [[a]] -> [[a]] 
revrev = foldl (\ acc xs -> reverse xs : acc) [] 

Если вы хотите играть в гольф-код, вы можете написать это как

revrev=foldl(flip((:).reverse))[] 

, но не делают этого.

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