Использование cons с tail of tail в списке выдает ошибку

#haskell #cons

#haskell #cons

Вопрос:

Я новичок в Haskell, и я в основном пытаюсь понять, почему это не удается:

 Prelude> test
[2,3,4,1]
Prelude> tail $ tail test
[4,1]
Prelude> 2 : [4,1]
[2,4,1]
Prelude> 2 : tail $ tail test

<interactive>:27:1: error:
    • Couldn't match expected type ‘[Integer] -> t’
                  with actual type ‘[Integer]’The first argument of ($) takes one argument,
      but its type ‘[Integer]’ has none
      In the expression: 2 : tail $ tail test
      In an equation for ‘it’: it = 2 : tail $ tail test
    • Relevant bindings include it :: t (bound at <interactive>:27:1)

<interactive>:27:5: error:
    • Couldn't match expected type ‘[Integer]’
                  with actual type ‘[a0] -> [a0]’Probable cause: ‘tail’ is applied to too few arguments
      In the second argument of ‘(:)’, namely ‘tail’
      In the expression: 2 : tail
      In the expression: 2 : tail $ tail test
Prelude>
 

Я вижу сообщение об ошибке «Вероятная причина: ‘tail’ применяется к слишком небольшому количеству аргументов», но я недостаточно понимаю, чтобы понять, что его вызывает, потому что это же выражение только что сработало.

Комментарии:

1. 2 : tail $ tail test эквивалентно (2 : tail) (tail test) , не 2 : (tail (tail test))

2. @WillemVanOnsem: это сработало! Спасибо. Как я упоминал в другом ответе, я попробовал 2 : $ tail $ tail test , и он вернулся parse error on input ‘$’ . Знаете ли вы, почему это так?

Ответ №1:

Вам нужно знать о группировке / приоритете операторов: 2 : tail $ tail test это не то же самое, что «cons 2 на значение tail $ tail test «, не больше, чем 5 * 3 2 «умножить результат 3 2 на 5″. В обоих случаях вам нужно добавить круглые скобки, если вы хотите выполнить именно эту операцию.

Комментарии:

1. ах! Итак, я действительно попытался: 2 : $ tail $ tail test и это тоже не удалось. Насколько я понимаю, $ и ввод круглых скобок эквивалентны?

2. Помещение круглых скобок действительно работает! Спасибо за ответ. Если бы вы могли также объяснить, почему $ работает din, это было бы потрясающе!

3. $ не эквивалентно скобкам, но является способом избежать скобок, поскольку $ имеет более низкий приоритет, чем (почти) любой другой оператор.

4. @Yathi 2 : $ tail $ tail test не работает точно по той же причине, которая 5 * 3 2 не работает.

5. @Yathi, но (2:) $ tail $ tail test и (:) 2 $ tail $ tail test оба будут работать. (:) является фактической функцией, соответствующей : оператору, и (2 :) является либо (:) 2 или x -> 2 : x (я не помню, какой, и это очень редко имеет значение).