Betrachten Sie das folgende Beispielprogramm:Haskell: Überlappende Instanzen
next :: Int -> Int
next i
| 0 == m2 = d2
| otherwise = 3 * i + 1
where
(d2, m2) = i `divMod` 2
loopIteration :: MaybeT (StateT Int IO)()
loopIteration = do
i <- get
guard $ i > 1
liftIO $ print i
modify next
main :: IO()
main = do
(`runStateT` 31) . runMaybeT . forever $ loopIteration
return()
Es nur get
statt lift get
verwenden können, weil instance MonadState s m => MonadState s (MaybeT m)
im MaybeT Modul definiert ist.
Viele solcher Instanzen sind in Art einer kombinatorischen Explosionsweise definiert.
Es wäre schön gewesen (wenn auch nicht warum?), Wenn wir die folgende Typ-Klasse haben:
{-# LANGUAGE MultiParamTypeClasses #-}
class SuperMonad m s where
lifts :: m a -> s a
Lassen sie versuchen, es als solches zu definieren:
{-# LANGUAGE FlexibleInstances, ... #-}
instance SuperMonad a a where
lifts = id
instance (SuperMonad a b, MonadTrans t, Monad b) => SuperMonad a (t b) where
lifts = lift . lifts
Mit lifts $ print i
statt von liftIO $ print i
funktioniert, das ist schön.
Aber mit lifts (get :: StateT Int IO Int)
statt (get :: MaybeT (StateT Int IO) Int)
funktioniert nicht.
GHC (6.10.3) gibt den folgenden Fehler:
Overlapping instances for SuperMonad
(StateT Int IO) (StateT Int IO)
arising from a use of `lifts'
Matching instances:
instance SuperMonad a a
instance (SuperMonad a b, MonadTrans t, Monad b) =>
SuperMonad a (t b)
In a stmt of a 'do' expression:
i <- lifts (get :: StateT Int IO Int)
ich sehen kann, warum "instance SuperMonad a a
" gilt. Aber warum denkt GHC, dass der andere es auch tut?
+1 für ausgezeichnete Formulierung. –
danke! Nach Ihrer Eingabe habe ich es geschafft! – yairchu
OverlappingInstances sind weit entfernt auf meiner Liste der Erweiterungen (sogar noch weiter als UndecidableInstances, was die Arbeit des Compilers nur viel schwieriger macht) - nicht nur unportabel, sondern auch die Sicherheitsgarantien zu brechen, die Haskell normalerweise bietet. Ich würde OP raten, es aufzusaugen und sich damit zu befassen, Lift zu heben oder nicht manuell zu heben, anstatt diesen Hack hinzuzufügen ... aber das ist meine Meinung. – ephemient