Haskell: рекурсия с полиморфной функцией равенства - PullRequest
2 голосов
/ 14 сентября 2010

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

Given:
nameEQ (a,_) (b,_) = a == b
numberEQ (_,a) (_,b) = a == b
intEQ a b = a == b
member :: (a -> a -> Bool) -> a -> [a] -> Bool

Я добавил:

member eq x ys | length ys < 1 = False
               | head(ys) == x = True
            | otherwise = member(x,tail(ys))

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

phoneDB = [("Jenny","867-5309"), ("Alice","555-1212"), ("Bob","621-6613")]

> member nameEQ ("Alice","") phoneDB
True
> member nameEQ ("Jenny","") phoneDB
True
> member nameEQ ("Erica","") phoneDB
False
> member numberEQ ("","867-5309") phoneDB
True
> member numberEQ ("","111-2222") phoneDB
False
> member intEQ 4 [1,2,3,4]
True
> member intEQ 4 [1,2,3,5]
False 

не совсем уверен, что мне нужно делать здесь.Любая помощь или документация по этому вопросу было бы здорово.Спасибо!

Ответы [ 3 ]

7 голосов
/ 14 сентября 2010

Различные вещи (я не собираюсь выписывать полный ответ, так как это домашнее задание):

  1. length ys < 1 можно выразить более просто как null ys
  2. Вам не нужны скобки вокруг аргументов функции.head(ys) чаще записывается как head ys
  3. Вы можете, если хотите, превратить верхний регистр и два других в совпадения с образцом, а не в охранников.member eq x [] = ... будет соответствовать пустому регистру, member eq x (y:ys) = ... будет соответствовать непустому регистру.
  4. Вы используете == для сравнения.Но вместо этого вы должны использовать функцию eq, которую вы дали.
  5. Вы заключаете аргументы члена в скобки, как если бы это была Java или что-то подобное.В Haskell аргументы разделяются пробелами, поэтому member(x,(tail(ys)) должно быть member x (tail ys).
5 голосов
/ 14 сентября 2010

Те ошибки, которые вы скрываете "о том, что вы не правильный тип, а также что-то другое", важны.Они говорят вам, что не так.

Например, когда я впервые бросил ваш код в ghc, я получил:

Couldn't match expected type `a -> a -> Bool'
       against inferred type `(a1, [a1])'
In the first argument of `member', namely `(x, tail (ys))'
In the expression: member (x, tail (ys))
In the definition of `member':
    member eq x ys
             | length ys < 1 = False
             | head (ys) == x = True
             | otherwise = member (x, tail (ys))

Ну, когда я смотрю на это, это просто - вы 'Вы набрали

member(x,tail(ys))

Когда вы четко имели в виду:

member x (tail ys)

Запятые означают что-то в Haskell, что вы не собирались там делать.еще раз, что вы перевели аргумент eq на member.

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

2 голосов
/ 14 сентября 2010

Так как параметры a в member :: (a -> a -> Bool) -> a -> [a] -> Bool не выводите Eq, вы не можете использовать == для их сравнения, но вместо этого придется использовать данную функцию eq.

Поэтому ваш код может выглядеть так:

member :: (a -> a -> Bool) -> a -> [a] -> Bool
member eq x ys
 | length ys < 1 = False
 | eq x (head ys) = True
 | otherwise = member eq x (tail ys)

Единственная проблема с этим состоит в том, что длина по-прежнему требует оценки всего списка чтобы вы могли достичь лучшей производительности написания:

member' :: (a -> a -> Bool) -> a -> [a] -> Bool
member' eq x (y:ys)
 | eq x y = True
 | otherwise = member' eq x ys
member' _ _ [] = False

С помощью любого вы можете упростить его еще больше:

member'' :: (a -> a -> Bool) -> a -> [a] -> Bool
member'' f a = any (f a)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...