Skip to content

Warn about <$> in semantic actions #335

Open
@andreasabel

Description

@andreasabel

Accidentially writing <$> in monadic semantic actions gives complete incomprehensible type errors on the generated Haskell code.
Example from Agda code base (details do not matter):

DomainFreeBindingAbsurd :: { Either (List1 (NamedArg Binder)) (List1 Expr)}
DomainFreeBindingAbsurd
    : ...
    | '{{' Attributes1 CommaBIds DoubleCloseBrace
         {% Left <$> applyAttributes $2 (makeInstance defaultArgInfo) $3 }

I was faced with this error (details do not matter):

agda/dist-newstyle/build/aarch64-osx/ghc-9.10.1/Agda-2.8.0/build/Agda/Syntax/Parser/Parser.hs:5447:11: error: [GHC-83865]
    • Couldn't match expected type ‘Parser
                                      (Either (List1 (NamedArg Binder)) (List1 Expr))’
                  with actual type ‘Bool’
    • In the expression:
        Left
          < happy_var_4
              applyAttributes happy_var_2 (makeInstance defaultArgInfo)
              happy_var_3
      In a case alternative:
          (HappyWrap22 happy_var_4)
            -> (Left
                  < happy_var_4
                      applyAttributes happy_var_2 (makeInstance defaultArgInfo)
                      happy_var_3)
      In the expression:
        case happyOut22 happy_x_4 of
          (HappyWrap22 happy_var_4)
            -> (Left
                  < happy_var_4
                      applyAttributes happy_var_2 (makeInstance defaultArgInfo)
                      happy_var_3)
     |
5447 |         ( Left <happy_var_4 applyAttributes happy_var_2 (makeInstance defaultArgInfo) happy_var_3)}}})
     |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

agda/dist-newstyle/build/aarch64-osx/ghc-9.10.1/Agda-2.8.0/build/Agda/Syntax/Parser/Parser.hs:5447:17: error: [GHC-83865]
    • Couldn't match expected type: (List1 Attr
                                     -> ArgInfo
                                     -> f0 (NamedArg Binder)
                                     -> Parser (f0 (NamedArg Binder)))
                                    -> List1 Attr
                                    -> ArgInfo
                                    -> List1 (NamedArg Binder)
                                    -> a0
                                    -> Either a0 b0
                  with actual type: Range' SrcFile
    • The function ‘happy_var_4’ is applied to four visible arguments,
        but its type ‘Range’ has none
      In the second argument of ‘(<)’, namely
        ‘happy_var_4
           applyAttributes happy_var_2 (makeInstance defaultArgInfo)
           happy_var_3’
      In the expression:
        Left
          < happy_var_4
              applyAttributes happy_var_2 (makeInstance defaultArgInfo)
              happy_var_3
     |
5447 |         ( Left <happy_var_4 applyAttributes happy_var_2 (makeInstance defaultArgInfo) happy_var_3)}}})
     |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Ideally one would allow <$> in the semantic action code.
However, since $> is a code used by happy for the last variable, and Haskell does not require whitespace around operators, <$> actually can be interpreted by Happy. In my example, this expands to the nonsense:

Left < $3 applyAttributes $2 (makeInstance defaultArgInfo) $3 

So the door to allowing <$> is closed.

I think however a warning would be in order.
The probability for intentionally writing <$> in the meaning that happy reads into it is minuscule, so the vast majority of occurrences <$> should be by accident.
Happy should warn that there is a chance of confusion.
Should it be a false alert, it can be fixed by adding a space (< $>) or turning off the warning.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions