Функция «максимум» для списков работает только в отдельной функции? - PullRequest
0 голосов
/ 01 января 2019

У меня проблемы с пониманием ошибки Хаскелла, когда я перемещаю функцию Data.List maximum по разным частям моего кода.Я использую несколько встроенных функций, чтобы найти режим произвольного списка целых чисел.Например, когда mode дан список list = [1,2,3,4,5,5,6,6,5,5,4,4,3,4,5,6,7,8,6,5,3,2,5], он должен вернуть 5.

Когда я помещаю встроенную функцию maximum в мою функцию mode следующим образом:

mode l = case l of
    [] -> []
    (x : xs) ->
        let x = map length (group (sort l))
            y = map head (group (sort l))
        in  snd (maximum (zip x y)) --<-----<-----<-- This Line

и я запускаю mode на вышеупомянутом list с командой> mode list в ghci, это выдает мне следующую ошибку:

<interactive>:2:7: error:
* Couldn't match type `Integer' with `[a]'
  Expected type: [[a]]
    Actual type: [Integer]
* In the first argument of mode', namely `list'
  In the expression: mode' list
  In an equation for `it': it = mode' list
* Relevant bindings include it :: [a] (bound at <interactive>:2:1)

Однако, когда я разделил функцию mode на mode и mode' (при максимальном выполнении mode') примерно так:

mode' f l = snd (maximum (f l)) --<-----<-----<-- Now Here

mode l = case l of
    [] -> []
    (x : xs) ->
        let x = map length (group (sort l))
            y = map head (group (sort l))
        in  zip x y

и я запускаю mode на вышеупомянутом list с> mode' mode list в ghci я получаю ожидаемый вывод 5 без ошибок.

Кто-нибудь может объяснить, почему это так?

Ответы [ 2 ]

0 голосов
/ 01 января 2019

Когда вы говорите mode' mode, вы можете вставить следующее:

mode l = case l of
    [] -> snd (maximum [])
    (x : xs) ->
        let x = map length (group (sort l))
            y = map head (group (sort l))
        in snd (maximum (zip x y))

Обратите внимание, что это не то же самое, что ваш оригинал, потому что mode' применяется, если list пустоили нет, если ваш оригинал применяет его только в непустом случае.

Обратите внимание, что snd (maximum []) проверяет тип, но выдает ошибку времени выполнения Exception: Prelude.maximum: empty list.Это означает, что вам все еще нужно ответить на вопрос: что мне делать с пустым списком?

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

mode l = case l of
    [] -> Nothing
    _ ->
        let x = map length (group (sort l))
            y = map head (group (sort l))
        in Just (snd (maximum (zip x y)))

(обратите внимание, что я заменил неиспользуемый шаблон (x : xs) на _, чтобы избежать путаницы при повторном определении x в let.)

0 голосов
/ 01 января 2019

Более подробно рассмотрим оператор case в mode:

В вашем рабочем примере:

mode l = case l of
    [] -> []
    (x : xs) -> let ... in zip x y

Тип возврата mode - это список.В ломаной версии:

mode l = case l of
    [] -> []
    (x : xs) -> let ... in snd (maximum (zip x y))

Тип возврата в первой ветви - это список, но во 2-й ветви - это Integer (как zip x y :: [(Integer, a)]).Это ошибка типа.

В рабочем случае другая ветвь mode возвращает список, поэтому тип допустим: mode :: (Num a, Ord b) => [b] -> [(a, b)] и mode' проверки типов.

Сообщение об ошибке Couldn't match type 'Integer' with '[a]' говорит о том, что функция ожидала список [a], но вместо этого получила Integer: ваш список содержит целые числа, поэтому вы можете сказать, что функция ожидала, что аргумент будет списком списков:тогда тип действителен (mode :: Ord a => [[a]] -> [a]).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...