Como instâncias indecidíveis podem realmente travar o compilador?
Quando li pela primeira vez sériocríticas sobre-XUndecidableInstances
, Eu já tinha me acostumado completamente, vendo-o apenasremoção de uma restrição irritante que Haskell98 precisa facilitar a implementação de compiladores.
Na verdade, eu encontrei muitos aplicativos em que instâncias indecidíveis eram necessárias, mas nenhuma em que elas realmente causaram problemas relacionados à indecidibilidade. O exemplo de Lucas é problemático por uma razão bem diferente
class Group g where
(%) :: g -> g -> g
...
instance Num g => Group g where
...
- bem, isso seria claramentesobreposto por qualquerGroup
Por exemplo, a indecidibilidade é a menor das nossas preocupações: isso é realmentedeterminista!
Mas, justamente, eu mantive “instâncias indecidíveis podem travar o compilador” na parte de trás da minha cabeça.
De onde foi adquirido quando liesse desafio no CodeGolf.SE, solicitando código que paralisaria infinitamente o compilador. Bem, parece um trabalho para instâncias indecidíveis, certo?
Acontece que não consigo convencê-los a fazê-lo. O seguinte compila rapidamente, pelo menos a partir do GHC-7.10:
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
class C y
instance C y => C y
main = return ()
Eu posso até usar métodos de classe, e eles só causam um loop emtempo de execução:
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
class C y where y::y
instance C y => C y where y=z
z :: C y=>y; z=y
main = print (y :: Int)
Mas os loops de tempo de execução não são nada incomuns; você pode codificá-los facilmente no Haskell98.
Também tentei loops diferentes e menos diretos, como
{-# LANGUAGE FlexibleContexts, UndecidableInstances #-}
data A x=A
data B x=B
class C y
instance C (A x) => C (B x)
instance C (B x) => C (A x)
Novamente, não há problema no momento da compilação.
Então, o que é realmente necessário para desligar o compilador na resolução de instâncias de classe de tipo indecidíveis?