2015-08-20 5 views
11

Geist der folgenden Klasse:Wie schreiben Sie Rewrite-Regeln für Typklassenmethoden?

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

ich auch verlangen, dass toList . fromList == id. Wie schreibe ich Rewrite-Regeln, um GHC anzuweisen, diese Ersetzung vorzunehmen?

+4

Das ist eigentlich nicht "offensichtlich". Das ist eine Eigenschaft, die Sie explizit verlangen müssen. Zum Beispiel könnten Sie eine Baumstruktur haben, die Sie in eine Liste umwandeln können und die Sie auch aus einer Liste konstruieren können, aber wo diese Identität nicht unbedingt gilt. – Cubic

+0

Das klingt vernünftig. Vielen Dank. – MaiaVictor

+0

Kann auch 'l' nicht zwischen den' toList' und 'fromList' Aufrufen unterscheiden? Zum Beispiel 'redBlackTreeToBTree = toList. fromList' wobei 'redBlackTreeToBTree :: RedBlackTree a -> BTree a' ist. –

Antwort

10

können Sie einen RULES Pragma verwenden diese Vereinfachung zu implementieren, aber Sie haben a bit of extra work zu tun, um die generische Methode Rewrite-Regeln nicht ausgelöst, um sicherzustellen, bevor Sie eine Chance haben, zu:

{-# 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 

Hier ist ein dummes Beispiel zu zeigen, dass es funktioniert:

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" 

Dies druckt Just "Hello" statt erroring aus. Außerdem können Sie sehen, die Regeln feuern:

$ 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 ...