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