2010-05-06 1 views
-2

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

..> реплицировать [5,1,3,2,8,1,2]

выход: [5,5,5,5,5,1, 3,3,3,2,2,8,8,8,8,8,8,8,8,1,2,2]

Я понял это с использованием понимания и рекурсии списка:

replicate2 [] = [] 
replicate2 (n:nn) = take n(repeat n) ++ replicate2 nn 

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

так что любая помощь будет хорошо, спасибо!

+7

Ничего себе - все четыре вопроса начинаются «Как вы решаете это» и все домашнее задание. Пожалуйста, приложите больше усилий для понимания проблемы и задайте вопрос подмножества, который разъяснит ваше понимание более широкого аспекта (Haskell). –

+0

alrite, я отвечу на ваш совет. спасибо –

+1

, вы можете подумать о добавлении тега «do-my-homework-you-suckers». люди на SO - хорошие люди, которые любят помогать. но они не любят тратить больше усилий на ваши проблемы, чем вы готовы потратить на них самостоятельно – yairchu

ответ

6

Ключ в Haskell всегда следуют типы:

foldr :: (a -> b -> b) -> b -> [a] -> b 
foldr1 :: (a -> a -> a)  -> [a] -> a 
map :: (a -> b)   -> [a] -> [b] 
take :: Int    -> [a] -> [a] 

Я добавил некоторые пробелы здесь, чтобы сделать его немного более ясно, как эти три функции сравнения. Помните, когда вы смотрите на них, что переменная типа a или b может соответствовать любому типу, включая такие вещи, как String, или [Float], или даже [(String,[Int])]. Например, в выражении:

foldr (\a b -> product a + b) (0::Int) [[1,2,4],[5,2],[0,3,6]] 

foldr используется в качестве типа ([Int] -> Int -> Int) -> Int -> [[Int]] -> Int. То есть a соответствует [Int] и b соответствует Int.

В настоящее время: Подумайте на уровне «внешнего», что должно делать ваше выражение. Какая из этих функций подходит для этой формы?

Можете ли вы превратить свою проблему в внешнее выражение, которое имеет одну из этих форм и «внутреннюю» проблему?

2

У вас есть ваш заказ прикладного приложения. Подумайте о том, что вы должны быть в состоянии сделать:

  1. Включите ряд n в список n копий себя
  2. Применить операции # 1 на каждый номер в списке
  3. сцепить все списки вы получили от # 2 вместе.

Вы знаете, как сделать 1: take n $ repeat n
2 и 3, которая является map и которая является fold?

Шаг 2. является map - вы являетесь сопоставление («преобразование») каждого элемента в списке, в список.
Шаг 3. является fold, так как вы агрегируя («сплющивание») кучу элементов списка в один.

+0

Привет, спасибо за помощь, 2 - это сгиб и 3 карта. Но я не могу заставить взять n повторить n, чтобы взять Int, потому что что-то вроде foldl1 (take $ repeat) [2,2] не работает. Я думал использовать foldl1 для оценки каждого из списков с помощью take $ repeat, а затем использовать карту, чтобы собрать все это вместе. но как я могу использовать захват и складывать вместе? –

+0

Я думаю, что 2 - карта, а 3 - фолд. –

+0

Да, это наоборот - я обновил свой ответ еще немного. – tzaman

1
replicate2 lst = concatMap(\x -> (take x) (repeat x)) lst 
+2

Вы также можете использовать 'Control.Applicative'. 'concatMap (принять <*> повтор)'. – hammar

1
replicate xs = foldl (++) [] (map (\n->take n $ repeat n) xs) 

Идея заключается в карты на каждом элементе списка, который просто повторяет элемент х, х число раз. Затем сверните в список, чтобы объединить его. Предположим, что этот список является [5,1,2]

Таким образом, (map (\n->take n $ repeat n) xs) является [[5,5,5,5,5], [1], [2,2]] , а затем вам просто нужно объединить внутренние списки.

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