Opened 7 years ago

Last modified 15 months ago

#1087 new bug

bang patterns with infix ops

Reported by: dons Owned by:
Priority: normal Milestone:
Component: Compiler (Parser) Version: 6.6
Keywords: bang patterns Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Difficulty: Unknown
Test Case: Blocked By:
Blocking: Related Tickets:

Description

    $ ghci -fbang-patterns

-- Ok

    Prelude> let at a !b = False in at 1 2
    False

    Prelude> let (.!.) a !b = False in 1 .!. 2
    False

-- ~ patterns are ok

    Prelude> let a `at` ~b = False in at 1 2
    False

    Prelude> let a .!. ~b = False in 1 .!. 2
    False

    Prelude> let ~a .!. b = False in 1 .!. 2
    False

-- Parse error if we combine bang patterns with infix decls:

    Prelude> let a .!. !b = False in 1 .!. 2
    <interactive>:1:10: parse error on input `!'

    Prelude> let a `at` !b = False in at 1 2
    <interactive>:1:11: parse error on input `!'

    Prelude> let !a .!. b = False in 1 .!. 2
    <interactive>:1:5: Parse error in pattern

So looks like ops and infix declarations are missing a case for bang patterns.

-- Don

Change History (7)

comment:1 Changed 7 years ago by benl

  • Summary changed from Bang pattern parsing with infix ops to had a look into it, might be best to leave it as it is.

I don't think fixing this is going to be straight forward because '~' is a reserved op whereas '!' isn't. There's a conflict between bang patterns and use of a single '!' as an operator.

We could allow bang patterns with infix decls by changing the infixexp rule as follows:

infixexp 
	: exp10	
	| infixexp qop bang_exp10
        | '!' aexp qop bang_exp10     -- (A) 
 
bang_exp10 
        : exp10
        | '!' exp10

However, adding the rule marked (A) to get them on the right hand side of the qop introduces a boatload (43) of shift/reduce conflicts into the parser, all at the following point:

State 236

	infixexp -> '!' . aexp qop bang_exp10               (rule 303)
	special_sym -> '!' .                                (rule 516)

	'_'            shift, and enter state 111
			(reduce using rule 516)

	'as'           shift, and enter state 11
			(reduce using rule 516)

	'derive'       shift, and enter state 12
			(reduce using rule 516)

        ... lots more

This is due to infixexp being used to parse patterns as well as expressions. ie, when parsing something like:

! (a, b) + c = ...

After accepting the '!' we won't know if !(a, b) is a pattern or a single argument operator application until we get to the '+'.

If we just do the shift and go for the bang pattern then we loose the ability to partially apply '!' as an operator like so:

let f = (! x)

... which seems likely to break existing code.

In summary, it might be best to leave the parser as it is and require operators using bang patterns to be defined in prefix form, at least for now. Either that or make a single '!' a reserved op like '~' is and choose some other operator for Array indexing. Perhaps a question for Haskell'.

comment:2 Changed 7 years ago by benl

  • Summary changed from had a look into it, might be best to leave it as it is. to bang patterns with infix ops

comment:3 Changed 7 years ago by benl

  • Difficulty changed from Easy (1 hr) to Unknown

comment:4 Changed 7 years ago by igloo

  • Milestone set to _|_

comment:5 Changed 6 years ago by simonmar

  • Architecture changed from Unknown to Unknown/Multiple

comment:6 Changed 6 years ago by simonmar

  • Operating System changed from Unknown to Unknown/Multiple

comment:7 Changed 15 months ago by morabbin

  • Type of failure set to None/Unknown

Behavior confirmed in GHC 7.6.1.

Note: See TracTickets for help on using tickets.