Как я должен реорганизовать этот код на Haskell, чтобы сделать его более элегантным? - PullRequest
6 голосов
/ 02 апреля 2011

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

concatFirstFour :: [Char] -> [Char]
concatFirstFour (a:b:c:d:_) = (replicate 1 a) ++ (replicate 1 b) ++ (replicate 1 c) ++ (replicate 1 d)
concatFirstFour xs = error "Need at least four characters."

Обновление: Большое спасибо всем. Я узнал несколько вещей из всех ответов и комментариев. Я гораздо лучше понимаю типы.

Вот код, который я использовал в итоге:

initFirstFour :: [a] -> [a]
initFirstFour str 
               | length str > 3 = take 4 str
               | otherwise      = error "Need at least four characters."

Обновление 2: Изменен второй шаблон с xs на _ для комментария ptival. Ленивый eval FTW.

Обновление 3: Очистить стражу от комментария tew88.

Ответы [ 4 ]

10 голосов
/ 02 апреля 2011
concatFirstFour (a:b:c:d:_) = [a,b,c,d]
concatFirstFour _           = error "Need at least four characters."

или

concatFirstFour = take 4

но последний не сбой в коротких списках ...


Также обратите внимание, что вам не нужно указывать тип [Char] (или String), поскольку вы никогда не используете это предположение в коде. Пусть это будет [a] -> [a].

4 голосов
/ 03 апреля 2011

Возможно, вы захотите использовать ключевое слово 'else' как часть вашего защитного выражения:

initFirstFour :: [a] -> [a]
initFirstFour xs
    | length xs > 3 = take 4 xs
    | otherwise     = error "Need at least four characters."

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

4 голосов
/ 02 апреля 2011

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

Во-первых, если вам нужен список только с одним элементом, вы можете использовать [x].Итак:

concatFirstFour (a:b:c:d:_) = [a] ++ [b] ++ [c] ++ [d]

Но на самом деле это не обязательно.Вы можете просто сделать это:

concatFirstFour (a:b:c:d:_) = [a, b, c, d]

Или это:

concatFirstFour (a:b:c:d:_) = a:b:c:d:[]

Или, мой предпочтительный способ:

concatFirstFour str = take 4 str

Поскольку str это просто списокВы можете take первые четыре символа, чтобы получить новую "строку".

2 голосов
/ 02 апреля 2011

Аналогично решению Ptival с использованием сопоставления с образцом. Но это не ошибка со строками менее 4 символов.

concatFirstFour (a:b:c:d:_) = [a,b,c,d]
concatFirstFour xs       = xs
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...