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 ...
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
To brzmi rozsądnie. Dzięki. – MaiaVictor
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'. –