2015-08-05 3 views
2

Функция valueOf получает значение Int соответствующего String из списка кортежей. Может кто-нибудь объяснить, как работает третья линия?Поиск единственного элемента в списке с использованием понимания списка

type State = [(String,Int)] 

valueOf :: State -> String -> Int 
valueOf xs var = head [b | (a,b) <- xs , a ==var ] 

Я никогда не видел выражение Haskell, как это, я больше привык к выражению, как это:

(\xs -> length xs > 15) 
+2

Обратите внимание, что это не очень хорошая реализация. 'head', как правило, неодобрительно; это определенно не безопасное использование (программа просто выйдет из строя, если ключ не будет найден, без труда увидеть, где все пошло не так). Лучше было бы что-то вроде этого: 'valueOf :: State -> String -> Maybe Int'. Для этой безопасной подписи есть фактически стандартные функции, доступные для поиска, как вы хотите: 'lookup' или' find'. Кроме того, рассмотрите [переход на «Карта»] (http://hackage.haskell.org/packages/archive/containers/latest/doc/html/Data-Map-Lazy.html), который более эффективен для таких поисков. – leftaroundabout

ответ

8

Нет выражения лямбда. То, что вы видите, - это понимание списка, которое является способом создания списка значений, удовлетворяющих определенному условию.

В этом случае понимание [b | (a,b) <- xs , a ==var ] означает что-то вроде: создать список всех b с таким образом, что (a, b) является элементом списка xs, где a равно var.

В императивном псевдо-код, который вы могли бы написать это как

result = EMPTY_LIST 
for (a,b) in xs: 
    if a == var: 
     result.add(b) 
return result 

Таким образом, вся valueOf функция работает путем создания списка значений, которые имеют ключ правой String, а затем использует head функцию, чтобы получить первый один. Обратите внимание, что если совпадения нет, произойдет полное вычисление.

4

(a,b) <- xs не лямбда, то генератор в list comprehension

В этом случае он последовательно связывает пары в исходном списке xs и сопоставляет их с (a, b). Булевая защита a == var сохраняет все элементы, для которых верно a == var.

4

Линия

valueOf xs var = head [b | (a,b) <- xs , a ==var ] 

эквивалентно выражению лямбда

valueOf = \xs var -> head [b | (a,b) <- xs , a ==var ] 

Однако, я думаю, что на самом деле вас смущает список понимание [b | (a,b) <- xs , a ==var ]. Это выражение строит список следующим образом: цикл по всем парам в xs (это часть (a,b)<-xs), сохраняйте только те пары, где a==var, затем возьмите все оставшиеся b и создайте список с ними.

С head спереди это просто выглядит в xs для первой пары, первым компонентом которой является var, и возвращает ее второй компонент. Если такой пары не обнаружено, будет генерироваться ошибка времени выполнения (если xs не является бесконечным списком, что вызовет запуск программы навсегда).

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