fun c = elem [1..10] работает в GHCi, но не компилируется - PullRequest
3 голосов
/ 26 марта 2020

В GHCi при выполнении этой команды

func = elem [1..10]

Работает просто отлично и возвращает мне частичную функцию. Мне интересно, почему это работает? Когда я пытаюсь скомпилировать этот код, он выдает ошибку. Например, это не работает работа с другими функциями. Карта дает мне ошибку в GHCi и когда я его компилирую.

func = map [1..10]

Любопытно, что особенного в GHCi и функции elem.

Я знаю, что могу написать это как:

func = (`elem` [1..10])

func = (`map` [1..10])

И это работает, но почему работает другой способ для элем.

1 Ответ

4 голосов
/ 26 марта 2020

elem [1..10] - совершенно разумный термин. Пример:

Prelude> elem [1..10] [[0..9], [1..10]]
True
Prelude> elem [1..10] [[0..8], [1..7]]
False

Возможно, чаще всего это будет написано

Prelude> [1..10] `elem` [[0..9], [1..10]]
True
Prelude> [1..10] `elem` [[0..8], [1..7]]
False

, но это просто другая версия syntacti c той же вещи.

Это означает также, что можно скомпилировать, вам просто нужно дать ему соответствующую подпись (или попросить GH C сделать ее для вас). Например,

f :: [[Int]] -> Bool
f = elem [1..10]

... это функция, которая сообщает, содержит ли список числовых списков список [1..10]. То есть, как и при любом другом использовании elem, он сообщает вам, содержит ли какой-либо список элемент. Тот факт, что этот элемент сам по себе является списком, не имеет значения.

С другой стороны, map [1..10] просто неверен, поскольку первым аргументом map должна быть функция . И списки, хотя они могут быть элементами списков, никогда не могут быть функциями .

Это совсем другая история с разделами оператора (`elem`[1..10]) и (`map`[1..10]). В этих примерах [1..10] на самом деле является аргументом second . В этом разделе пропущен левый / первый аргумент. Таким образом, в данном случае мы говорим о

Prelude> 3 `elem` [1..10]
True
Prelude> 19 `elem` [1..10]
False

... и это также работает с

Prelude> negate `map` [1..10]
[-1,-2,-3,-4,-5,-6,-7,-8,-9,-10]

, хотя это будет более обычно написано map negate [1..10] или negate<$>[1..10].


В некотором смысле это одновременно pedanti c и anarchi c, списки могут фактически быть функциями: с расширение -XOverloadedLists, вы можете написать экземпляр класса, который позволит вам определять функции, используя синтаксис списка. Я не понимаю, как это могло бы иметь какой-то смысл, но, может быть, хорошо осознавать эту теоретическую возможность. В частности, с этим включенным расширением map [1..10] сбивает с толку компилирует , и вы просто получаете сбивающую с толку ошибку, связанную с Could not deduce ... The type variable ‘a0’ is ambiguous gibberi sh в другом месте.

...