2016-04-14 3 views
0

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

--delete element from list 
removeElement :: [a] -> [a] 
removeElement x [] = [] 
removeElement x aList = 
    if (head aList) == x 
     then removeElement x (tail aList) 
     else aList 

Ошибка я получаю это:

Couldn't match expected type `[[a]] -> [[a]]' 
       with actual type `[a]' 
    Relevant bindings include 
     removeElement :: [a] -> [a] (bound at hwmk3.hs:8:1) 
    The equation(s) for `removeElement' have two arguments, 
    but its type `[a] -> [a]' has only one 

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

+1

Подпись говорит, что ваша функция имеет один аргумент, а уравнение говорит, что у нее два. Имейте в виду, это * может * иметь смысл в Haskell, просто, вероятно, не то, что вам нужно здесь. –

ответ

5

Несколько вещей:

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

Кроме того, поскольку вы используете == для сравнения, вам нужно убедиться, что ваш тип имеет тип Eq.

Ваш тип аннотации должен вероятно выглядеть следующим образом:

removeElement :: Eq a => a -> [a] -> [a] 

Вы также можете упростить, воспользовавшись сопоставления с образцом. Вам не нужно использовать head и tail если вы определяете функцию следующим образом:

removeElement x [email protected](y:ys) = 
    if y == x 
    then removeElement x ys 
    else aList 

Однако, есть логическая ошибка в вашем условном операторе. Поскольку это звучит как домашнее задание, я оставлю его вам, чтобы найти ответ. Подсказка, попробуйте removeElement 3 [1, 2, 3]

+0

Ах, это больше функция, которую я собирался, я просто не знал о синтаксисе. Спасибо! Это очень помогло. –

0

Вашего типа подпись должна быть

removeElement :: a -> [a] -> [a] 

Кроме того, это выглядит как ваша функция не делать то, что вы думаете, он будет делать.

1

Если вы опустили явное объявление типа своей функции, Haskell предположил бы что-то вроде a -> [a] -> [a]. Фактически, все еще ... это, поэтому, вы жалуетесь, что не согласен с вашим заявленным типом.

Проблема, о которой сообщает Haskell, заключается в следующем. Глядя на свое второе уравнении, desugars к

removeElement x = \aList -> if (head aList) == x then removeElement x (tail aList) else aList 

несколько вещей, которые являются "очевидными":

  1. x :: [a] в качестве аргумента removeElement.
  2. Выражение лямбда имеет тип t -> v для некоторых типов t и v.

Но мы уже говорили, что removeElement :: [a] -> [a], поэтому мы можем придумать значений t и v таким образом, что [a] ~ t -> v? Может быть. Давайте будем выводить типы.

t является тип aList, который мы можем сделать вывод о head aList == x быть [[a]]. Пропуская рекурсивный вызов, мы также видим, что aList - это возвращаемое значение, поэтому v также является [[a]]. Таким образом, t -> v действительно [[a]] -> [[a]].

Можно ли сопоставить значение типа [[a]] -> [[a]] с [a]?

Нет, поэтому вы получаете точное сообщение об ошибке, которое вы делаете.