Haskell, определяющий приоритет операторов над функциями

Я должен получить тип этой функции:

func x = map -1 x

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

func = \x -> (map) - (1 x)

Если я выражаю это так, это нормально, и я получаю тот же тип, что и оригинал, но я не уверен, почему это сгруппировано так. Может кто-нибудь объяснить это?

Например, почему это не так:

func = \x -> (map - 1) x

или что-то подобное.

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

Если вы напишите эту функцию в файле, например: test.hs имеет func x = map -1 xи использовать :t func в переводчике он ответит:

func :: (Num (t -> (a -> b) -> [a] -> [b]),
         Num ((a -> b) -> [a] -> [b])) =>
         t -> (a -> b) -> [a] -> [b]

3 ответа

Решение

Теперь я верю, что вы хотели спросить, почему

func x = map -1 x

имеет тип (Num (t -> (a -> b) -> [a] -> [b]), Num ((a -> b) -> [a] -> [b])) => t -> (a -> b) -> [a] -> [b]и как вы можете заключить в скобки выражение, чтобы оно имело этот тип.

Во-первых, вы должны признать, что пробел является оператором в haskell и имеет самый высокий приоритет среди всех.

Давайте использовать # вместо пробела с наивысшим приоритетом мы можем:

infixl 9 #
f # x = f x

Мы можем заменить и пробел без оператора с #:

func x = map - 1 # x

потому что пространство между 1 и x было единственным без оператора (- находится между map а также 1).

поскольку # имеет более высокий приоритет, чем -, мы получаем

func x = map - (1 # x)

или эквивалентно

func x = map - (1 x)

Другой пример

func2 x = map (-1) x
> :t func2
func2 :: Num (a -> b) => [a] -> [b]

Это переводится как

func2' x = map # (-1) # x

но почему нет # между - и 1? В этом случае, - перед числовым буквенным как 1 средства negate:

> (-1)
-1
> (negate 1)
-1
> (subtract 1)
<interactive>:73:1:
    No instance for (Show (a0 -> a0))
      arising from a use of `print'
    Possible fix: add an instance declaration for (Show (a0 -> a0))
    In a stmt of an interactive GHCi command: print it

Таким образом, эта функция пытается отобразить минус 1 по списку. Для того, чтобы это работало, ей понадобится отрицательный 1, чтобы быть функцией, поэтому ему нужен числовой экземпляр для функций (Num (a->b) => в начале типа).

но я не уверен, почему это сгруппировано так. Может кто-нибудь объяснить это? Например, почему это не так:

   func = \x -> (map - 1) x

Внеочередные. Определение языка указывает, что приоритет приложения функции (префикса) выше, чем у любого инфиксного оператора, поэтому

map -1 x

анализируется как приложение инфиксного оператора (-) на два операнда map а также 1 x, лайк 3 + 4 * 5 анализируется 3 + (4 * 5) из-за более высокого приоритета (*) по сравнению с (+),

Хотя интерпретатор назначил тип выражению, он не является разумным. Посмотрим, какой должна быть функция

func x = map -1 x

Похоже, мы хотим заключить в скобки, как это

func x = map (-1) x

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

func x = map ((-) 1) x

Теперь эта функция вычитает каждое число в списке из 1:

 func [1,2,3]
=[(-) 1 1,  (-) 1 2,   (-) 1 3]
=[  1-1,      1-2,        1-3]
=[   0,       -1,         -2]

Тип является

func :: Num a => [a] -> [a]

Если вы хотите вычесть по одному из каждого элемента списка, а не вычитать каждый элемент списка из 1, вы можете использовать func x = map (subtract 1) x, Как указывает Хаммар, subtract Функция существует именно с целью разрешения этого.


Ваша альтернатива

func = \x -> (map - 1) x

Это не может работать, потому что (-) имеет тип Num a => a -> a -> a, в то время как map имеет тип (a -> b) -> [a] -> [b], Вы не можете вычесть одно из функции, потому что функция не является числовым значением.

Другие вопросы по тегам