2015-08-20 13 views
11

uwagę następujące klasy:Jak piszesz zasady przepisywania dla metod typeclass?

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

ja również zażądać toList . fromList == id. Jak napisać reguły przepisywania, aby poinformować GHC o dokonaniu tej zamiany?

+4

To nie jest "oczywiste". To własność, którą musisz wyraźnie żądać. Na przykład możesz mieć strukturę drzewa, którą możesz przekonwertować na listę i którą możesz także skonstruować z listy, ale tam, gdzie ta tożsamość niekoniecznie musi istnieć. – Cubic

+0

To brzmi rozsądnie. Dzięki. – MaiaVictor

+0

Nie można również odróżnić 'l' między wywołaniami' toList' i 'fromList'? Na przykład 'redBlackTreeToBTree = toList. fromList' gdzie 'redBlackTreeToBTree :: RedBlackTree a -> BTree a'. –

Odpowiedz

10

Można użyć RULES pragmy do wdrożenia tego uproszczenia, ale trzeba zrobić a bit of extra work aby upewnić się, że zasady przepisujące metoda rodzajowa nie ogień, zanim twoje mają szansę:

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

Oto głupi przykład aby pokazać, że to działa:

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" 

drukuje Just "Hello" zamiast erroring zewnątrz. Możesz także zobaczyć zasady zwalniania:

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