添加上下文以重写规则

时间:2017-02-17 09:40:15

标签: haskell optimization ghc

在以下代码中,我希望尽可能将g . f重写为h。可能有h个案例没有得到类的实例,但我希望在可能的情况下进行重写。我收到一条错误消息,表明这是可以实现的,但我不确定我需要改变什么。

以下是一些示例代码:

{-# LANGUAGE TypeFamilies #-}

main = return ()

data D a

f :: a -> D a
f = undefined

type family T a

class G a where
  g :: D (T a) -> a

class H a where
  h :: T a -> a

{-# RULES
  "myrule" forall x. g (f x) = h x
#-}

这是错误:

• Could not deduce (H a) arising from a use of ‘h’
  from the context: G a
    bound by the RULE "myrule" at trickyrewrite.hs:19:3-34
  Possible fix: add (H a) to the context of the RULE "myrule"
• In the expression: h x
  When checking the transformation rule "myrule"

请注意可能的解决方法: add (H a) to the context of the RULE "myrule" 。这似乎可以完成这项工作,但我不确定如何实际做到这一点。规则中甚至没有提及a,所以我不确定H a在没有引用任何内容时如何添加a会有所帮助。

如果它有任何区别,我控制的唯一代码是类H。我无法改变G。我的代码当然比这更复杂,但是如果我能看到一个如何使这个简化示例工作的工作示例,我应该能够计算出我认为的代码。

尝试失败:

我已尝试过@ Alec的建议,但它似乎无法正常工作,重写规则未被触发。这是我尝试过的代码:

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeApplications #-}

module Main where

main = ((g (f (2 :: Int))) :: Char) `seq` return () 

data D a

{-# INLINE [1] f #-}
f :: a -> D a
f = undefined

type family T a
type instance T Char = Int

{-# INLINE [1] g' #-}
g' :: (G a) => D (T a) -> a
g' = undefined

class G a where
  g :: D (T a) -> a
  g = g'

instance G Char

class H a where
  h :: T a -> a

{-# RULES
  "myrule" forall (x :: H a => T a). g' (f x) = h @a x
#-}

1 个答案:

答案 0 :(得分:4)

通常one can add type signatures to the variables in the forall。像

这样的东西
{-# RULES "myrule" forall (x :: H a => T a). g (f x) = h x #-}

现在,在这种情况下, 幸运的是,我认为TypeApplications允许我们告知GHC T类型a中的类型变量T ax中的那个:

h

我们不需要启用{-# LANGUAGE TypeFamilies, TypeApplications, AllowAmbiguousTypes #-} ... {-# RULES "myrule" forall (x :: H a => T a). g (f x) = h @a x #-} (即使我们依赖它来确保ScopedTypeVariables是相同的),因为它在重写规则中默认启用。