2016-11-12 2 views
0

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

search :: a -> [(a,b)] -> Maybe b 
search a (x:xs) = if a == first value in x, return second value in x 
-- If a is not in the list of tuples, return "Nothing" 

Примером этого может быть:

search "x" ([("x", 3), ("z", 5)]) = 3 
search "x" ([("y", 3), ("z", 5)]) = Nothing 
+0

Что такое 'S'? И как это не _exactly_ так же, как 'lookup'? – leftaroundabout

+0

Я удалил, что S, извинения, это было из неправильно выполненного кода. Потому что lookup возвращает «Just x», а не «x». –

+3

Да, но если тип возврата - «Может быть, b», то вы _can_ только возвращаете 'Just x'. Сам по себе «х» имеет неправильный тип ('b', а не' Maybe b'). – leftaroundabout

ответ

1

В базовом случае, если список пуст, он возвращает Nothing. Затем, если первый элемент a кортежа в голове равен элементу x, он возвращает второй элемент Just b. Иначе, рекурсивно, он ищет в хвосте.

search :: (Eq a) => a -> [(a,b)] -> Maybe b 
search _ [] = Nothing 
search x ((a,b):xs) = if x == a then Just b else search x xs 

Вы можете реализовать небезопасную версию без Maybe:

search :: (Eq a) => a -> [(a,b)] -> b 
search _ [] = error "element not found" 
search x ((a,b):xs) = if x == a then b else search x xs 

Другого варианта поиск списка вместо первого вхождения, то пустой список [] эквивалентно Nothing:

search :: (Eq a) => a -> [(a,b)] -> [b] 
search x = map snd . filter ((==x).fst) 
+0

Я думаю, что OP хотела помочь понять, почему ее код не работает, а не решение. Если бы это была последняя, ​​она могла бы найти определение 'lookup'. – Alec

+0

Нет, я хочу знать, как заставить этот код работать. Я хочу написать эту функцию под названием «поиск», а не просто использовать функцию поиска. Я просто знаю, что он похож на функцию поиска –

+1

Я думаю, что неплохо предложить небезопасную версию. – duplode

2

find может извлечь первый элемент, удовлетворяющий произвольному условию, и поэтому вы можете bui Л.Д. вашей функции вокруг него:

-- 'fmap snd' acts on the 'Maybe (a, b)' that 'find' gives back. 
search :: Eq a => a -> [(a,b)] -> Maybe b 
search a = fmap snd . find ((== a) . fst) 

Обратите внимание, что это точно так же, как и lookup. Кроме того, как указано в левой части, 3 (в отличие от Just 3) не является возможным результатом для функции с типом результата Maybe b. Вы можете устранить Maybe обертывание, когда вы на самом деле нужно использовать результат, используя, например, maybe функция:

GHCi> :t maybe 
maybe :: b -> (a -> b) -> Maybe a -> b 
GHCi> (maybe "No x" (("x ~> " ++) . show) . search "x") ([("x", 3), ("z", 5)]) 
"x ~> 3" 
GHCi> (maybe "No x" (("x ~> " ++) . show) . search "x") ([("y", 3), ("z", 5)]) 
"No x" 
0

Просто используйте простую карту в сочетании с лямбда:

searchMe :: (Eq a) => a -> [(a, b)] -> [Maybe b] 
searchMe a li = map (\(x, y) -> if a == x then Just y else Nothing) li 

OP вашей функции , так как это не будет работать, поскольку вы определяете свой параметр списка как (x: xs), который не позволит вам применять операции к элементам кортежа.

+0

(1) '(Eq a) => a -> [(a, b)] -> [Maybe b]' будет работать нормально - в вашей реализации, только 'x' должен иметь один и тот же тип' a '. (2) Это дает список 'Maybe a', в то время как OP хочет только первое значение' Just' в списке. Вам нужно что-то вроде 'listToMaybe. catMaybes' (оба находятся в 'Data.Maybe') для выполнения этого последнего шага. – duplode

Смежные вопросы