2015-08-20 26 views
11

mente la seguente classe:Come si scrivono le regole di riscrittura per i metodi di tipizzazione?

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

ho anche chiedere che toList . fromList == id. Come scrivo le regole di riscrittura per dire a GHC di fare quella sostituzione?

+4

In realtà non è "ovvio". Questa è una proprietà che devi esplicitamente richiedere. Ad esempio, potresti avere una struttura ad albero che puoi convertire in una lista e che puoi anche costruire da una lista, ma dove questa identità non è necessariamente valida. – Cubic

+0

Sembra ragionevole. Grazie. – MaiaVictor

+0

Inoltre, non si può 'l differire tra le chiamate' toList' e 'fromList'? Ad esempio 'redBlackTreeToBTree = toList. fromList' dove 'redBlackTreeToBTree :: RedBlackTree a -> BTree a'. –

risposta

10

è possibile utilizzare un pragma RULES di attuare questa semplificazione, ma si deve fare a bit of extra work per assicurarsi che le regole di riscrittura metodo generico non sparare prima del vostro hanno la possibilità di:

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

Ecco un esempio stupido per dimostrare che funziona:

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" 

Questo stampa Just "Hello" invece di erroring fuori. Inoltre, puoi vedere l'attivazione delle regole:

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