你如何为类型类方法编写重写规则? [英] How do you write rewrite rules for typeclass methods?

查看:89
本文介绍了你如何为类型类方法编写重写规则?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  class ListIsomorphic l其中
toList :: l a - > [a]
fromList :: [a] - > l a

我还要求 toList。 fromList == id 。如何编写重写规则来告诉GHC进行替换?

解决方案

您可以使用 RULES 编译指示来实现这种简化,但您必须执行一些额外的工作以确保通用方法重写规则在您有机会之前不会触发:

  { - #RULES 
protect toList toList = toList;
protect fromListfromList = fromList';
fromList / toListforall x。 fromList'(toList'x)= x; # - }

{ - #NOINLINE [0] fromList'# - }
fromList'::(ListIsomorphic l)=> [a] - > l a
fromList'= fromList

{ - #NOINLINE [0] toList'# - }
toList'::(ListIsomorphic l)=> l a - > [a]
toList'= toList

下面是一个愚蠢的例子,

 实例ListIsomorphic可能其中
toList = errortoList
fromList = errorfromList

test1 ::可能a - >也许
test1 x = fromList(toList x)

main = print $ test1 $只是你好

这会打印只是你好而不是出错。此外,您可以看到规则解雇:

  $ ghc -O -ddump-rule-firing --make rewrite-method。 hs 
编译Main(rewrite-method.hs,rewrite-method.o)
规则被解雇:protect toList
规则被解雇:保护fromList
规则被解雇:解开
解雇规则:解开
解雇规则:保护解雇
解雇规则:保护解雇
规则解雇:fromList / toList
解雇规则:解开
规则被解雇:Class op show
被解雇的规则:>#
被解雇的规则:tagToEnum#
被解雇的规则:Class op showsPrec
被解雇的规则:Class op showList
被解雇的规则:++
规则解雇:解包列表
规则解雇:foldr / app
规则解雇:解包列表
规则解雇:解包列表
链接重写 - method.exe ...


Mind the following class:

class ListIsomorphic l where
    toList    :: l a -> [a]
    fromList  :: [a] -> l a

I also demand that toList . fromList == id. How do I write rewrite rules to tell GHC to make that substitution?

解决方案

You can use a RULES pragma to implement this simplification but you have to do a bit of extra work to make sure the generic method rewrite rules don't fire before yours have a chance to:

{-# RULES
  "protect toList"   toList = toList';
  "protect fromList" fromList = fromList';
  "fromList/toList"  forall x . fromList' (toList' x) = x; #-}

{-# NOINLINE [0] fromList' #-}
fromList' :: (ListIsomorphic l) => [a] -> l a
fromList' = fromList

{-# NOINLINE [0] toList' #-}
toList' :: (ListIsomorphic l) => l a -> [a]
toList' = toList

Here's a silly example to show that it works:

instance ListIsomorphic Maybe where
    toList = error "toList"
    fromList = error "fromList"

test1 :: Maybe a -> Maybe a
test1 x = fromList (toList x)

main = print $ test1 $ Just "Hello"

This prints Just "Hello" instead of erroring out. Also, you can see the rules firing:

$ ghc -O -ddump-rule-firings --make rewrite-method.hs
[1 of 1] Compiling Main             ( rewrite-method.hs, rewrite-method.o )
Rule fired: protect toList
Rule fired: protect fromList
Rule fired: unpack
Rule fired: unpack
Rule fired: protect toList
Rule fired: protect fromList
Rule fired: fromList/toList
Rule fired: unpack
Rule fired: Class op show
Rule fired: >#
Rule fired: tagToEnum#
Rule fired: Class op showsPrec
Rule fired: Class op showList
Rule fired: ++
Rule fired: unpack-list
Rule fired: foldr/app
Rule fired: unpack-list
Rule fired: unpack-list
Linking rewrite-method.exe ...

这篇关于你如何为类型类方法编写重写规则?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆