#haskell
#haskell
Вопрос:
Я пытаюсь создать функцию, которая выводит char*m
n
время, такое, каким ожидаемый результат был бы ["ccc","ccc"]
для ввода 2 3 c
. Вот что у меня есть на данный момент:
rectangle :: Int -> Int -> Char -> [string]
rectangle n m c
| m > 0 = [concat ([[c]] (rectangle n (m-1) c))]
| otherwise = []
Я могу выполнить первую часть, char*m
поэтому она возвращает ["ccc"]
. Дело в том, что я также хотел бы иметь возможность повторять свою строку n
раз.
Я пытался использовать replicate, но, похоже, это не работает, хотя это работает, если делать это в консоли: replicate 2 (rectangle 2 3 c)
.
Ответ №1:
Попробуйте реплицировать функцию таким образом:
replicate :: Int -> a -> [a]
rectangle n m c = replicate n (replicate m c)
Кроме того, не забудьте указать, является ли это домашним заданием.
Комментарии:
1. Функция
replicate
принимает числоn
и значение и создает списокn
элементов этого значения. Таким образом,replicate 3 'a'
получается"aaa"
.2. Это отличное простое решение, однако есть ли у кого-нибудь решение, в котором используется предопределенная функция? поможет мне научиться 🙂
3. @Lunar Хорошим способом научиться было бы попытаться определить
replicate
самостоятельно. Я не мог придумать решение, которое каким-либо образом не требует использованияreplicate
.4. @Lunar: Обратите внимание, что
replicate
это в стандартной прелюдии (или, по крайней мере, повторно экспортируется прелюдией), но я добавил подпись типа, чтобы помочь.5. Будет ли какой-либо выигрыш в производительности, если мы сделаем что-то вроде: пусть t = replicate m c в replicate n t
Ответ №2:
В качестве дополнения к ответу рефакторинга, я думаю, что его подход является правильным. Он подразделяет проблему до тех пор, пока ее нельзя решить тривиально, используя встроенные функции. Если вы хотите внедрить свое собственное решение для целей обучения, я предлагаю вам сохранить это подразделение и перейти оттуда, реализуя свой собственный replicate. В противном случае вы получите единственную функцию, которая делает слишком много.
Итак, оставшаяся проблема заключается в реализации replicate. Моей первой идеей было бы взглянуть на исходный код replicate. Я нашел ее через hoogle, что привело меня к hackage, в котором есть ссылки на исходный код. Выдержка из исходного кода:
replicate :: Int -> a -> [a]
replicate n x = take n (repeat x)
это красиво и лаконично, опять же с использованием встроенных функций. Если вы хотите полностью выполнить свою собственную репликацию, вы можете сделать:
myReplicate :: Int -> a -> [a]
myReplicate n x | n <= 0 = []
| otherwise = x : replicate (n-1) x
———-РЕДАКТИРОВАТЬ—————-
В качестве примечания, я думаю, что ваша проблема требует двух довольно ортогональных навыков. Первый — это попытка не решать всю проблему сразу, а вместо этого добиться небольшого прогресса. Затем вы можете попытаться решить эту меньшую проблему, прежде чем возвращаться к более крупной. В вашем случае, скорее всего, потребуется признать, что вам определенно нужен способ преобразования символа в серию символов длиной n. Здесь вам поможет опыт работы с такими функциями, как map, filter, foldr и так далее, поскольку каждая из них представляет собой совершенно отдельное преобразование, которое вы можете распознать.
Второй навык, необходимый для вашего решения — если вы хотите создать свое собственное, — это распознавание того, когда функция может быть выражена рекурсивно. Как вы можете видеть, ваша проблема — и действительно, многие распространенные проблемы — могут быть решены без явной рекурсии, но это хороший навык, которым нужно обладать, когда возникает необходимость. Рекурсивные решения не всегда легко приходят в голову, поэтому я думаю, что лучший способ познакомиться с ними — прочитать и попрактиковаться.
Для дальнейшего изучения, я уверен, вам уже указали на отличные Learn You a Haskell и Real World Haskell, но на всякий случай, если вы этого не сделали, вот они.
Комментарии:
1. Спасибо, каждая задача, которую я даю себе, кажется, терпит неудачу! и в большинстве случаев это можно сделать с помощью простых готовых функций, есть ли набор функций, которые, по вашему мнению, следует изучить и использовать, когда это возможно, таких как map, filter, replicate?
2. Опыт работы с такими функциями, как эти, определенно поможет вам. Я бы сказал, что существует базовый набор функций, которые полезно знать и использовать. Этот набор нечеткий / четко не определен, но он включает в себя общие функции списка, такие как отображение, фильтр и т.д. Я расширил свой ответ, чтобы уточнить, как они могут помочь.