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 ...
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
Das klingt vernünftig. Vielen Dank. – MaiaVictor
Kann auch 'l' nicht zwischen den' toList' und 'fromList' Aufrufen unterscheiden? Zum Beispiel 'redBlackTreeToBTree = toList. fromList' wobei 'redBlackTreeToBTree :: RedBlackTree a -> BTree a' ist. –