代码之家  ›  专栏  ›  技术社区  ›  Boris

Haskell operator vs function precedence

  •  35
  • Boris  · 技术社区  · 14 年前

    I am trying to verify something for myself about operator and function precedence in Haskell. For instance, the following code

    list = map foo $ xs
    

    can be rewritten as

    list = (map foo) $ (xs)
    

    and will eventually be

    list = map foo xs
    

    My question used to be, why the first formulation would not be rewritten as

    list = (map foo $) xs
    

    since function precedence is always higher than operator precedence, but I think that I have found the answer: operators are simply not allowed to be arguments of functions (except of course, if you surround them with parentheses). 这是对的吗?If so, I find it odd, that there is no mention of this mechanic/rule in RWH or Learn you a Haskell, or any of the other places that I have searched. So if you know a place, where the rule is stated, please link to it.

    --编辑:感谢您的快速回答。我想我的困惑来自于这样的想法:一个操作符文字会以某种方式对某个东西进行评估,而这个东西可能会被一个函数作为参数使用。它帮助我记住,中缀运算符可以机械地转换为前缀函数。这样做的第一个配方产生

    ($) (map foo) (xs)
    

    如果($)无疑是消费函数,并且由于这两个公式是等效的,那么第一个公式中的$literal不能被map消费。

    5 回复  |  直到 6 年前
        1
  •  25
  •   John L    14 年前

    你是对的。此规则是Haskell语法定义的一部分。 Haskell Report . 特别地,请注意第3节中的表达式,即函数应用程序的参数(AN) fexp )必须是 aexp . AEXP允许运算符作为节的一部分,也允许在带圆括号的表达式中,但不允许使用裸运算符。

    map foo $ xs ,haskell语法意味着它被解析为两个表达式,应用于二进制运算符。 $ . As sepp2k notes, the syntax (map foo $) is a left section and has a different meaning.

    我不得不承认,我从来没有考虑过这个问题,事实上,我必须在报告中查一下,看看为什么操作员会有他们所做的行为。

        2
  •  35
  •   K.Karamazen    6 年前

    Firstly, application (whitespace) is the highest precedence "operator".

    其次,在haskell中,运算符和函数之间实际上没有区别,除了默认情况下运算符是中缀,而函数不是。您可以使用反勾号将函数转换为中缀

    2 `f` x
    

    (+) 2 3
    

    So, your question is a bit confused.

    Prelude> :info ($)
    ($) :: (a -> b) -> a -> b   -- Defined in GHC.Base
    
    infixr 0 $
    
    Prelude> :info (+)
    
    class (Eq a, Show a) => Num a where
      (+) :: a -> a -> a
    
    infixl 6 +
    

    Showing both precedence and associativity.

        3
  •  15
  •   mucaho    9 年前

    In addition to the information provided by other answers already, note that different operators can have different precedences over other operators, as well as being left-/right- or non-associative. You can find these properties for the Prelude operators in the Haskell 98 Report fixity section .

    +--------+----------------------+-----------------------+-------------------+
    | Prec-  |   Left associative   |    Non-associative    | Right associative |
    | edence |      operators       |       operators       |    operators      |
    +--------+----------------------+-----------------------+-------------------+
    | 9      | !!                   |                       | .                 |
    | 8      |                      |                       | ^, ^^, **         |
    | 7      | *, /, `div`,         |                       |                   |
    |        | `mod`, `rem`, `quot` |                       |                   |
    | 6      | +, -                 |                       |                   |
    | 5      |                      |                       | :, ++             |
    | 4      |                      | ==, /=, <, <=, >, >=, |                   |
    |        |                      | `elem`, `notElem`     |                   |
    | 3      |                      |                       | &&                |
    | 2      |                      |                       | ||                |
    | 1      | >>, >>=              |                       |                   |
    | 0      |                      |                       | $, $!, `seq`      |
    +--------+----------------------+-----------------------+-------------------+
    

    Any operator lacking a fixity declaration is assumed to be left associative with precedence 9 .

    记住,函数应用具有最高优先级(考虑优先级) 10 与表中的其他优先级相比) [1] .

        4
  •  11
  •   Paul Kuliniewicz    14 年前

    The difference is that infix operators get placed between their arguments, so this

    list = map foo $ xs
    

    can be rewritten in prefix form as

    list = ($) (map foo) xs
    

    which, by the definition of the $ operator, is simply

    list = (map foo) xs
    
        5
  •  9
  •   sepp2k    14 年前

    Operators can be passed as function arguments if you surround them with parenthesis (i.e. map foo ($) xs , which would indeed be passed as (map foo ($)) xs )但是,如果您没有用括号括起来,那么您就可以正确地认为它们不能作为参数(或分配给变量)传递。

    Also note that the syntax (someValue $) (何处) $ could be any operator) actually means something different: it is equivalent to \x -> someValue $ x , i.e. it partially applies the operator to its left operand (which in case of $ is a noop of course). 同样地 ($ x) partially applies the operator to the right operand. 所以 map ($ x) [f, g, h] would evaluate to [f x, g x, h x] .

    推荐文章