Ticket #6102 (closed feature request: invalid)

Opened 12 months ago

Last modified 12 months ago

Subclass Specialization in Rewrite Rules

Reported by: SamAnklesaria Owned by: SamAnklesaria
Priority: normal Milestone:
Component: Compiler Version: 7.4.1
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Difficulty: Unknown
Test Case: Blocked By:
Blocking: Related Tickets:

Description

Rewrite rules can define a specialized version of a method for some specific datatype, but they cannot currently define a specialized version of a method for some specific superclass.

class ClassOne a where
   classOneOp :: a -> a 

class ClassOne a => ClassTwo a where
   classTwoOp :: a -> a

data ClassInstance = ...

instance ClassOne ClassInstance where
   classOneOp = ...

specialFunc :: ClassInstance -> ClassInstance
specialFunc = ...

{-# RULES
"willcompile"        forall i. classOneOp i = specialFunc
"wontcompile"      forall i. classOneOp i = classTwoOp i
   #-}

Although we can specialize classOneOp for ClassInstance?, we can't do so for those instances of ClassOne? that are also instances of ClassTwo?.

Change History

  Changed 12 months ago by SamAnklesaria

  • owner set to SamAnklesaria

  Changed 12 months ago by simonpj

  • difficulty set to Unknown

Correct, and I see no way to avoid this. Consider

foo :: ClassOne a => a -> a
foo x = classOneOp (classOneOp a)

Imagine firing rule "wontcompile" on the source code. You'd get:

foo :: ClassOne a => a -> a
foo x = classTwoOp (classTwoOp a)

But that's ill-typed! classTwoOp needs (ClassTwo a) and that simply isn't available in foo.

However THIS should work:

"wontcompile"      forall i. classOneOp i = classTwoOp i :: ClassInstance

Note the signature, so that the rule fires only when specialised to ClassInstance.

But it still doesn't:

T6102.hs:19:45:
    Could not deduce (ClassTwo ClassInstance)
      arising from a use of `classTwoOp'
    from the context (ClassOne ClassInstance)
      bound by the RULE "wontcompile" at T6102.hs:19:1-73
    Possible fix:
      add an instance declaration for (ClassTwo ClassInstance)
    In the expression: classTwoOp i :: ClassInstance
    When checking the transformation rule "wontcompile"

That's a bug. I'll look at it.

  Changed 12 months ago by simonpj

  • status changed from new to closed
  • resolution set to invalid

Oh silly me. Of course ClassInstance is not an instance of ClassTwo. If you add such an instance all is well. Code below compiles fine

module T6102 where

class ClassOne a where
   classOneOp :: a -> a

class ClassOne a => ClassTwo a where
   classTwoOp :: a -> a

data ClassInstance = A | B

instance ClassOne ClassInstance where
   classOneOp _ = A

instance ClassTwo ClassInstance where
   classTwoOp _ = B

specialFunc :: ClassInstance -> ClassInstance  
specialFunc _ = A

{-# RULES
"willcompile"      forall i. classOneOp i = specialFunc
"alsocompiles"     forall i. classOneOp i = classTwoOp i :: ClassInstance
 #-}

So I'll close this.

follow-up: ↓ 5   Changed 12 months ago by SamAnklesaria

I don't think I expressed the feature request very well. The idea was that rewriting would only occur when the types matched. "willcompile" will only change classOneOp to specialFunc when the result is a ClassInstance?. Likewise, I was thinking it would be useful to have "wontcompile" only change classOne to classTwoOp when the result is shown to be an instance of ClassTwo?. In your example, one couldn't assume that the result of classOneOp (classOneOp a) was an instance of ClassTwo?, and the rewrite wouldn't happen.

I don't know if this kind of behavior is possible, but it isn't something that would produce ill typed expressions.

in reply to: ↑ 4   Changed 12 months ago by simonpj

Replying to SamAnklesaria:

Likewise, I was thinking it would be useful to have "wontcompile" only change classOne to classTwoOp when the result is shown to be an instance of ClassTwo?.

I'm afraid I don't know how to achieve that!

Note: See TracTickets for help on using tickets.