Si consideri il seguente programma di esempio:Haskell: sovrapposizione casi
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()
Si può usare solo get
invece di lift get
perché instance MonadState s m => MonadState s (MaybeT m)
è definito nel modulo MaybeT.
Molte di queste istanze sono definite in modo di esplosione combinatoria.
Sarebbe stato bello (anche se impossibile perché?), Se abbiamo avuto la seguente tipo di classe:
{-# LANGUAGE MultiParamTypeClasses #-}
class SuperMonad m s where
lifts :: m a -> s a
Proviamo a definirlo come tale:
{-# 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
Utilizzando lifts $ print i
invece di liftIO $ print i
funziona, che è bello.
Ma l'utilizzo di lifts (get :: StateT Int IO Int)
invece di (get :: MaybeT (StateT Int IO) Int)
non funziona.
GHC (6.10.3) dà il seguente errore:
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)
Posso capire perché "instance SuperMonad a a
" si applica. Ma perché GHC pensa che anche l'altro lo faccia?
+1 per una formulazione eccellente. –
grazie! seguendo il tuo contributo sono riuscito a farlo! – yairchu
Sovrapposizioni Le istanze sono molto più in basso nella mia lista di estensioni (anche oltre le UndecidableInstances, che rendono il lavoro del compilatore molto più difficile) da usare - non solo non trasportabili, ma anche rompere le garanzie di sicurezza normalmente fornite da Haskell. Suggerirei OP a succhiarlo e gestire 'lift'ing o no' lift'ing manualmente, piuttosto che aggiungere questo hack in ... ma questa è la mia opinione. – ephemient