Haskell не может сопоставить ожидаемый тип «a» с фактическим типом «[a0]»

Я делаю проект на Haskell, где я пытаюсь создать функцию, которая принимает два входа списка, а затем возвращает объединение списка, но без каких-либо дубликатов.

Проблема в том, что я продолжаю получать сообщение об ошибке:

Couldn't match expected type ‘a’ with actual type ‘[t0]’
      ‘a’ is a rigid type variable bound by
          the type signature for newList :: [a] -> [a] -> [a]

Вот мой код:

allList :: (Eq a) => [a] -> [a] -> [a]
allList [] [] = []
allList x y = (x ++ y)

checkDup [] = []
checkDup (z:zs)
    | z `elem` zs = checkDup zs
    | otherwise = z : checkDup zs

newList :: (Eq a) => [a] -> [a] -> [a]
newList [] [] = []
newList x y = [checkDup z | z <- allList x y]

Первая функция allList создает список из двух списков, checkDup создает новый список без каких-либо дубликатов, а newList использует понимание списка для передачи объединенного списка в checkDup.

Кто-нибудь знает, где я ошибаюсь?


person Elsa Slättegård    schedule 13.04.2016    source источник
comment
Три небольших замечания, которые, я надеюсь, помогут вам изучить Haskell: 1) allList и newList не нужны их первые случаи. 2) Вам не нужно Eq для сопоставления с образцом, поэтому allList на самом деле не нужно ограничение Eq a. 3) Если убрать ненужный код, о котором я говорил, то allList будет просто псевдонимом для (++). Вы можете написать x ++ y вместо allList x y в newList и удалить функцию allList (если упражнение каким-то образом не требует от вас ее определения и использования, или если вы считаете, что с ней код становится более читаемым).   -  person    schedule 14.04.2016


Ответы (2)


Проблема здесь:

newList x y = [checkDup z | z <- allList x y]

z должен быть списком, который вы передаете checkDup, но в этом случае z — это всего лишь один элемент

Возможно, вы хотите:

newList x y = checkDup $ allList x y

newList можно объявить следующим образом:

newList :: (Eq a) => [a] -> [a] -> [a]
newList = checkDup . allList
person smac89    schedule 13.04.2016
comment
Пожалуйста, всегда пишите пробелы вокруг оператора композиции. Если вы этого не сделаете, это будет слишком похоже на уточнение имени. - person ; 14.04.2016

Поскольку @Smac89 ответил на ваш вопрос, почему бы не использовать представление данных, например Data.Set?

import qualified Data.Set as S

allList :: Ord a => [a] -> [a] -> [a]
allList xs ys = S.toList $ S.union (S.fromList xs) (S.fromList ys)

(хотя дальнейшее использование Sets, вероятно, имеет еще большее значение.)

Или с помощью Data.List:

import Data.List

newList :: Eq a => [a] -> [a] -> [a]
newList xs ys = nub $ xs ++ ys
person Simon Shine    schedule 13.04.2016
comment
Да, обычно я бы это сделал, но это для школьного проекта, и нам не разрешено использовать какой-либо импорт. - person Elsa Slättegård; 13.04.2016