Executar o seguinte no GHCi gera um erro em stuff' 4
mas não em stuff 4
. Por quê?
Existe uma maneira de consertar isso? Eu gostaria de usar MkStuff'
e não MkStuff
.
ghci>
:{
class MkStuff s m | m -> s where
stuff:: s -> m ()
instance MkStuff Int IO where
stuff = print
class MkStuff' s m | m -> s where
stuff' :: s -> m
instance MkStuff' Int (IO ()) where
stuff' = print
:}
ghci> stuff 4
4
ghci> stuff' 4
<interactive>:16:1: error: [GHC-39999]
• No instance for ‘MkStuff' Integer ()’ arising from a use of ‘it’
• In the first argument of ‘print’, namely ‘it’
In a stmt of an interactive GHCi command: print it
Embora eu não tenha certeza absoluta, acredito que é isso que acontece.
O GHCi tem alguma mágica dentro. Após inserir uma expressão, o GHCi tenta aproximadamente o seguinte:
Tente inferir
e :: IO a
para algunsa
. Se possível:a. Verifique se
a
é umShow
tipo. Se for, execute a açãoe
e então imprima seu valor resultante do tipoa
(a menos quea~()
).b. Caso contrário, execute a ação
e
e imprima oa
valor resultante.Caso contrário, tente inferir
e :: a
para algunsa
da classeShow
. Se possível, imprima a string obtida porshow e
.Caso contrário, imprima um erro de tipo.
No seu primeiro caso, ao inferir
stuff 4 :: IO a
GHCi pode ver questuff 4 :: m ()
, portantom ~ IO
. Isso pode ser usado para confirmar sua instância, e tudo prossegue suavemente.No seu segundo caso, ao inferir
stuff' 4 :: IO a
GHCi pode ver questuff' 4 :: m
, portantom ~ IO a
. Isso não é suficiente para confirmar a instância porque a instância é sobreIO ()
, ea
não foi (ainda) inferida como()
. Se outra instânciainstance MkStuff' Char (IO Bool) where ...
existisse, ela poderia fornecer outro candidato, então não podemos confirmar.Falhando na etapa 1, passamos para a etapa 2, mas nada concreto
a
pode ser encontrado. Regras padrão trya ~ ()
, daí seu erro estranhoNo instance for ‘MkStuff' Integer ()’
. Infelizmente, essa inadimplência ocorre tarde demais no processo para permitir o commit na instância IO.Tente tornar o cabeçalho da instância mais geral:
Isso permite corretamente que o GHCi faça commit na instância. Note que você não poderá adicionar mais instâncias envolvendo
IO
dessa forma.