2015-11-27 6 views
-3

Я пишу очень простую функцию репликации, которая берет список номеров и возвращает список с каждым дублированием. Функция репликации, которая принимает значение и элемент, для меня более тривиальна, поскольку она не требует сохранения состояния.Любой способ сохранить значения в Haskell?

Но в Haskell, я получил это до сих пор:

> replicate' [] = [] 
> replicate' (x:xs) 
>   | x == 1 = x: replicate' xs 
>   | otherwise = x: replicate'(x-1:xs) 

, который, очевидно, неправильно, так как для replicate' [2,2], было бы напечатать [2,1,2,1] вместо [2,2,2,2]

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

Упс, люди немного смутились с вопросом.

Например, вызов replicate' [2,3,1] должен вернуться [2,2,3,3,3,1], а не только [2,2,3,3,1,1], как я думаю, что вы, ребята, думаете

+0

Написание вашей проблемы, безусловно, является хорошим первым шагом к ее решению. Например: «' replicate'' в списке '(x: xs)' есть (число 'x' в начале списка, повторяющееся' x' раз), добавленное к (хвост списка 'replicate'' -ed)». Если мы укажем проблему на _declarative_ way (описывая, что наши функции _are_), мы получаем что-то, что мы можем перевести непосредственно в haskell (заменить «is» на '='). – jberryman

ответ

3
replicate' [] = [] 
replicate' (x:xs) = x:x:replicate' xs 

Вы можете просто добавить две вещи сразу.

*Main> replicate' [1,2,3] 
[1,1,2,2,3,3] 

UPD:

duplicate::Int->Int->[Int] 
duplicate 0 x = [] 
duplicate n x = x:duplicate (n-1) x 

replicate' [] = [] 
replicate' (x:xs) = duplicate x x ++(replicate' xs) 
+0

Это не вдвое больше, это зависит от переменной. Подобно 'replicate '[1,2,3]' будет выводить '[1,2,2,3,3,3]' – Homerdough

+0

@Homerdough обновил ответ. –

+0

@ ig-melnyk Ваша функция 'duplicate' эквивалентна' replicate' (из Prelude). – Jubobs

5

Я знаю, что я должен сохранить х в какой-либо другой переменной

Нет, вы не знаете. Это предложение указывает на то, что у вас есть недоразумение. Я предлагаю вам подумать, почему вы считаете, что это правда, и исправить это понимание.

Что касается вашей проблемы, у вас есть хорошее начало, показывающее, что вы знаете о рекурсии, базовых случаях и базовом синтаксисе. Хорошая работа. Код, который вы предоставили, был:

replicate' [] = [] 
replicate' (x:xs) 
      | x == 1 = x: replicate' xs 
      | otherwise = x: replicate'(x-1:xs) 

Базовый кейс хорош, но почему вы вычитаете его из x? и почему он появляется (снова) в повторном вызове? Просто подумайте о той операции, которую вы хотите, нет никакой арифметики для элементов - вы хотите построить список, который повторяет каждый элемент, а синтаксис - как newelement : rest - мы можем читать : как «минусы». Таким образом, ваш второй случай должен быть:

replicate' (x:xs) = x : x : replicate' xs 

Edit снова, так как вы уточнили, что элементы числа, которые указывают, сколько раз они должны появиться. Ну, очевидное решение состоит в использовании копировщика (от основания) в качестве части replicate':

replicate' [] = [] 
replicate' (x:xs) = replicate x x ++ replicate' xs 

В приведенном выше описании мы реплицировать каждый элемент число раз, равных значению элемента затем сцепить этот список, с помощью ++ , к рекурсивному вызову.Более простая версия:

replicate' = concatMap (\x -> replicate x x) 

Например:

Prelude> concatMap (\x -> replicate x x) [1..3] 
[1,2,2,3,3,3] 
1

Основываясь на вашей логике (но плохой пример) я предполагаю, что вы хотите повторить каждый элемент столько раз, значение указывает ([2,3] -> [2,2,3,3,3]) ,

Вы можете написать repeat' функцию repeat' n = take n $ repeat n и использовать в функции репликатов

replicate' :: [Int] -> [Int] 
replicate' [] = [] 
replicate' (x:xs) = repeat' x ++ replicate' xs 

UPDATE:

Вы можете написать функцию повтора»рекурсивно, а, вам нужно использовать вспомогательную функцию несут дополнительную информацию о счете. Нечто подобное должно работать

rep :: Int -> [Int] 
rep x = rep' x x 
    where rep' x 0 = [] 
     rep' x n = x: rep' x (n-1) 

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

+0

Это то, что я ищу, но для моего задания я не знаю, разрешено ли нам использовать 'take' или' repeat'. Возможно ли переписать их в рекурсивной форме? В нем конкретно говорится: «Вы можете использовать определение вложенного помощника» Работает отлично btw – Homerdough

+0

Вы можете заменить 'repeat 'n' на' replicate n n'. Тем не менее, вы можете захотеть сделать «concatenate vanish» для лучшей эффективности. – Jubobs

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