Eu tenho um tipo de termo que, em essência, é:
data Term a = Term a Bool
deriving Show
O Bool
é um tipo de ajudante, e é necessário apenas ocasionalmente. Gostaria que o usuário pudesse ignorá-lo se não for necessário. Ou seja, o seguinte deve funcionar:
main :: IO ()
main = print v
where v = "a"
=: Term "b" True
=: []
onde:
class Join a b where
(=:) :: a -> [b] -> [b]
infixr 1 =:
instance Join a (Term a) where
x =: y = Term x False : y
instance Join (Term a) (Term a) where
x =: y = x : y
Infelizmente, o GHC reclama:
a.hs:15:8-12: error: [GHC-39999]
• Ambiguous type variable ‘b0’ arising from a use of ‘print’
prevents the constraint ‘(Show b0)’ from being solved.
Relevant bindings include v :: [b0] (bound at a.hs:17:8)
Mas se eu escrever main
assim:
main :: IO ()
main = print v
where v :: [Term String]
v = "a"
=: Term "b" True
=: []
Então está tudo bem. (Observe que a única diferença é que dei v
uma assinatura de tipo.)
Estou curioso para saber se existe algum truque moderno do GHC (famílias de tipos, famílias de tipos injetivos, famílias de tipos fechados, GADTs, etc., ou algum sinalizador mágico) que tornaria a assinatura de tipo desnecessária e permitiria que o GHC deduzisse o tipo sozinho, sem qualquer ajuda.
Aqui está o programa na íntegra:
data Term a = Term a Bool
deriving Show
class Join a b where
(=:) :: a -> [b] -> [b]
infixr 1 =:
instance Join a (Term a) where
x =: y = Term x False : y
instance Join (Term a) (Term a) where
x =: y = x : y
main :: IO ()
main = print v
where v :: [Term String] -- Want to avoid this signature and let GHC deduce it.
v = "a"
=: Term "b" True
=: []
E a questão é se há algum recurso ou truque do GHC que eu possa aplicar para que a assinatura de tipo em v
não seja necessária. Também estou feliz em mudar a Join
classe ou adicionar novos parâmetros/dependências etc., desde que a definição local de v
possa ser escrita como está sem a assinatura de tipo.
Eu também apreciaria uma explicação de por que isso não seria possível, se houver uma boa razão legítima para que o que estou pedindo seja irracional. Parece-me que há informações de tipo suficientes para que o GHC deduza o tipo em si, mas suspeito que algum tipo de suposição de "mundo aberto" esteja acontecendo e nenhum dos truques de "família de tipos fechados" funcionará; se esse for realmente o caso. Para ser claro, estou perfeitamente feliz que a Join
classe nunca seja instanciada em nenhum outro tipo.