, Просто используйте разные имена и обращайтесь к тем во внешней области видимости.

могу сосредоточиться на функциональном мышлении, чтобы решить эту проблему простым способом, который также мог бы работать для очень длинных списков. Если у вас есть список, как:

["one", "two", "three", "four", "five"]

Я могу сказать, с какой длиной самое длинное слово довольно просто:

maximum $ map length ["one", "two", "three", "four", "five"]

Как бы я изменил предыдущее утверждение, чтобы вернуть строкутри?

 Jason Christa16 янв. 2011 г., 22:19
@Mark Byers Возвращает первое вхождение самого длинного слова.

Ответы на вопрос(6)

если у кого-то не было готового к использованиюmaximumByпростым способом будет шаблон / идиома decorate-sort-undecorate (который работает и в других языках, таких как Python или Scheme):

snd $ maximum $ map (\x -> (length x, x)) ["one", "two", "three", "four", "five"]

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

 sclv17 янв. 2011 г., 00:10
@ Джон, если вы просто делаете один проход по потоку данных, список любой длины вполне подойдет. Теперь строки с другой стороны ...
 Peaker06 февр. 2011 г., 23:09
@hvr: Проблема с методом decorate заключается в том, что он требует, чтобы x имел экземпляр Ord, даже если вы сравниваете только декорации. По соображениям производительности вы можете использовать метод decorate вместе сmaximumBy fst чтобы избежать необходимости Ord в самих элементах списка.
 hvr17 янв. 2011 г., 08:14
@ Джон, спасибо за указание на проблемуmaximum(By) повторная оценкаmax, о котором я не знал и удивил меня немногоmaximum простоfoldl1 max без сомнения элегантно все же)
 John L17 янв. 2011 г., 10:06
@hvr, ghc не настолько агрессивен в отношении обмена ценностями, как можно было бы ожидать (или надеяться). Очевидно, очень трудно гарантировать, что совместное использование не будет намного менее эффективным, чем перерасчет, поэтому ghc требует, чтобы совместное использование было явным с помощью выражений let-bound. И хотяmaximumBy реализация очень элегантна, она не разделяет вычисления.
 John L17 янв. 2011 г., 00:07
Даже сmaximumByэто полезно.maximumBy Функция будет пересчитывать длину (или какую-либо функцию сравнения) самого длинного текущего токена при каждом сравнении, тогда как decorate-sort-undecorate вычисляет длину только один раз. Эта версия заметно эффективнее даже при скромных размерах. Конечно, если вы используете списки любой длины, вам, вероятно, не следует использовать списки.

maximumBy (\x -> (x, length x)), fst, а такжеsnd в простой композиции сделать свое дело.

foldl (\accmax xs -> if length accmax < length xs then xs else accmax) [] ["one", "two", "three", "four", "five"]

но на самом деле в Haskell есть модуль с именемData.Ord который содержит функциюcomparing что почти как использованиеData.Function.on в верхнем ответе, кроме того, код заканчивается более идиоматическим.

g>import Data.Ord
g>import Data.List
g>let getLongestElement = maximumBy (comparing length)
getLongestElement :: [[a]] -> [a]
g>getLongestElement ["one", "two", "three", "four", "five"]
"three"

Код практически читается как английский. «Получите максимум, сравнив длину».

 dfeuer17 дек. 2014 г., 19:29
Другие не согласны и думаютcomparing это глупый особый случай. Мне все равно, но я слышал, что опытные люди жалуются на это.
Решение Вопроса

С помощьюmaximumBy, on а такжеcompare Вы можете написать выражение так:

import Data.List (maximumBy)
import Data.Function (on)

maximumBy (compare `on` length)  ["one", "two", "three", "four", "five"]
 Daniel Buckmaster31 окт. 2012 г., 04:28
Действительно элегантный Хорошее решение.
 Peaker06 февр. 2011 г., 23:05
compare `on` length являетсяcomparing length гдеcomparing изData.Ord.

Вычислитьlength aнужно пройти весь списокa, В этом конкретном случае использования вас интересует только самое длинное слово, а не точная его длина, поэтому вы можете написать в каждом списке функцию, которая идет настолько далеко, насколько это необходимо, чтобы определить, какое из них самое длинное. Это может сэкономить вам некоторую обработку:

module Main where

main = putStrLn $ longestWordInList ["one", "two", "three", "four"]

longestWordInList = go ""
  where go result [] = result
        go result (x:xs) = let result' = longestWord result x in
                               result' `seq` go result' xs

longestWord a b = go a b a b
  where go a _ _ [] = a
        go _ b [] _ = b
        go a b (_:as) (_:bs) = go a b as bs
 dfeuer17 дек. 2014 г., 19:28
Вам не нужно так много аргументов, чтобыgo, Просто используйте разные имена и обращайтесь к тем во внешней области видимости.longestWord a b = go a b where go a' _ = a ...

Ваш ответ на вопрос