исправление кода сортировки слиянием и слияния в haskell

#haskell

#хаскелл

Вопрос:

 merge ::(ord a) => [a] ->[a] -> [a]
merge [][] = []
merge [a][b] = [[a,b]|a<-mergesort [a],b<- mergesort [b]]

mergesort ::(a -> Bool) -> [a] -> [a]
mergesort [] = []
mergesort (x:xs) = if xs >=2 then mergesort xs else mergesort(x:xs)
                                 | comparision > 0 = x:xs
                                 | comparision <= 0 =  xs:x
                                  where comparision = x-xs
 

Это код, который я написал для merge и mergesort, и, конечно, это неправильно.

Не могли бы вы дать несколько советов по исправлению кода? пожалуйста, не давайте мне ответов….

Комментарии:

1. Блин. Там много ошибок. Охват их всех охватил бы примерно половину материала полного учебника по Haskell. Может быть, вам лучше начать с некоторых более простых функций обработки списков, чтобы немного попрактиковаться в основах, прежде чем пробовать алгоритм сортировки. Скажем, sum для суммирования всех чисел в списке; and для проверки, есть ли в списке False что-нибудь в нем; length для выяснения, сколько элементов в списке; может быть, специализированный filter или что-то, что принимает a [Char] и возвращает список символов верхнего регистра из него; и так далее.

Ответ №1:

В нынешнем виде единственная ошибка, которую выдает компилятор, — это:

 test.hs:8:34: error: parse error on input ‘|’
  |
8 |                                  | comparision > 0 = x:xs
  |                                  ^
 

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

Основная проблема заключается в том, что защита (то есть синтаксическая форма, в которой есть символ канала | , за которым следует условие) разрешена только на сайтах привязки (например, для уравнений функций или внутренних case операторов). Вы включили свой в неправильное положение. Не совсем понятно, что вы подразумеваете под этими охранниками, поэтому я не слишком уверен, как помочь вам поставить их в правильное положение.

Возможно, лучшая помощь, которую я могу оказать, — это описать, что они означают, с помощью некоторых абстрактных примеров, и позволить вам выяснить, куда вы хотите, чтобы они шли вместо этого. Возьмите это в качестве примера:

 f x y | cond1 = val1
      | cond2 = val2
      | cond3 = val3
 

Это определяет новую функцию с именем f , которая принимает два аргумента. Он называет аргументы x и y . Затем, чтобы решить, какое значение возвращать, он проверяет guardians, ища первое значение, которое оценивается True . Таким образом, если cond1 вычисляется значение to True , функция возвращает val1 ; если cond1 вычисляется значение to False , но cond2 вычисляется значение to True , функция возвращает val2 ; если cond1 и cond2 вычисляется значение to False , но cond3 вычисляется значение to True , функция возвращает val3 . (.. и если все три условия оцениваются False как , это создает исключение во время выполнения.)

Теперь давайте посмотрим на синтаксис, который вы использовали:

 mergesort (x:xs) = if xs >=2 then mergesort xs else mergesort(x:xs)
                                 | comparision > 0 = x:xs
                                 | comparision <= 0 =  xs:x
 

Здесь вы определяете новую функцию с именем mergesort , которая принимает один аргумент. Он сопоставляет этот аргумент с шаблоном x:xs . Затем появляется, чтобы вернуть результат if xs >=2 then mergesort xs else mergesort(x:xs) . Но что делают эти два дополнительных охранника? Я не знаю. Возможно, вы воображаете, что if comparision > 0 , тогда функция вернет x:xs вместо if xs >=2 then ... else ... . Если это так, вы должны написать это так:

 mergesort (x:xs) | comparision > 0 = x:xs
                 | comparision <= 0 = xs:x
                 | otherwise = if x >=2 then mergesort xs else mergesort(x:xs)
 

Или, возможно, вы воображаете, что if comparision > 0 , тогда рекурсивный вызов будет использовать x:xs вместо (x:xs) . Если это так, вы должны написать это так:

 mergesort (x:xs) | comparision > 0 = if x >=2 then mergesort xs else mergesort(x:xs)
                 | comparision <= 0 = if x >=2 then mergesort xs else mergesort(xs:x)
 

Я не уверен, что было задумано.

В любом случае, надеюсь, это поможет вам устранить вашу ошибку синтаксического анализа и приведет вас к тому, что вы сможете посмотреть на следующие ошибки компилятора и попытаться исправить их самостоятельно.

Ответ №2:

Пара вопросов, которые нужно задать себе:

  1. Что, в частности, вы пытаетесь сделать с функциями merge и mergesort ? Предположим, у меня есть список, который я хочу отсортировать — только один список, еще не разделенный. Какую функцию я должен вызвать, чтобы использовать вашу реализацию сортировки слиянием?
  2. На основе подписи типа mergesort :: (a -> Bool) -> [a] -> [a] , сколько аргументов должно mergesort быть?
  3. Каковы типы x и xs ? Все ли функции, которые вы применяете к переменным, определены для этих типов? Я вижу функции - , : , >= , и mergesort . Типы, указанные для этих функций (за исключением mergesort ) ghci :t , следующие:
    • (-) :: Num a => a -> a -> a . Это означает:
      1. (-) принимает два аргумента одного и того же типа. Этот тип должен принадлежать классу Num типов, то есть это должно быть какое-то число.
      2. (-) возвращает единственное значение этого типа.
    • (:) :: a -> [a] -> [a] . Это означает:
      1. (:) принимает аргумент одного типа и другой аргумент, представляющий собой список значений этого типа.
      2. (:) возвращает список значений этого типа.
    • (>=) :: Ord a => a -> a -> Bool . Это означает:
      1. (>=) принимает два аргумента одного и того же типа. Этот тип должен принадлежать Ord классу типов, то есть должна быть возможность сравнить два значения этого типа и сказать, что одно значение больше, меньше или равно другому значению. (В Prelude , это включает в себя все члены typeclass Num .)
      2. (>=) возвращает a Bool .

Вам также следует подумать о том, как вы хотите структурировать свою реализацию. Подумайте о том, как работает сортировка слиянием. Посмотрите на шаги, подумайте о том, как вы можете реализовать эти шаги как функции, и как вы можете соединить эти шаги вместе с одной mergesort функцией. После того, как вы спланировали дизайн, вам следует побеспокоиться о синтаксисе.

Комментарии:

1. ваш последний совет также можно сформулировать как «сначала напишите много очень коротких функций и используйте их для реализации вашей основной функции. не пытайтесь записать все это сразу. сначала определите отдельную функцию для каждого отдельного шага в вашем алгоритме. »