La classe MonadReader
è definita secondo la FunctionalDependencies
estensione, che permette dichiarazioni come
class Monad m => MonadReader r m | m -> r where
...
Ciò significa che per ogni monad m
, il r
è univocamente determinata da esso. Pertanto, non è possibile avere una singola monad m
che determina due diversi tipi di r
. Senza questo come una restrizione il compilatore non sarebbe in grado di digitare gli usi di controllo della classe.
La soluzione a questo è quello di scrivere le funzioni come
getA'sInt :: A -> Int
getA'sInt = undefined
getB'sString :: B -> String
getB'sString = undefined
foo :: (MonadReader A m) => m Int
foo = do
a <- asks getA'sInt
return $ a + 1
bar :: (MonadReader B m) => m String
bar = do
b <- asks getB'sString
return $ map toUpper b
Poi basta usare una tupla (A, B)
nell'implementazione attuale:
baz :: Reader (A, B) (Int, String)
baz = do
a <- withReader fst foo
b <- withReader snd bar
return (a, b)
C'è anche un withReaderT
per i casi più complessi.
Come esempio del motivo per cui non è permesso di impilare ReaderT
s, si consideri il caso
type App = ReaderT Int (Reader Int)
Quando si chiama ask
, che Int
ti riferisci? Può sembrare ovvio che in casi come
type App = ReaderT A (Reader B)
il compilatore dovrebbe essere in grado di capire quale usare, ma il problema è che la funzione ask
qui avrebbe il tipo
ask :: App ???
Dove ???
potrebbe essere A
o B
. È possibile ottenere intorno a questo un altro modo, non usando MonadReader
direttamente e la definizione di specifiche askA
e askB
funzioni:
type App = ReaderT A (Reader B)
askA :: App A
askA = ask
askB :: App B
askB = lift ask
baz :: App (Int, String)
baz = do
a <- askA
b <- askB
return (getA'sInt a, getB'sString b)
Ma sarà solo in grado di avere MonadReader A App
, non si può avere anche MonadReader B App
. Questo approccio potrebbe essere chiamato "sollevamento esplicito" e rende tali funzioni specifiche per il tipo App
e quindi meno componibili.
Oh, 'istanza (MonadReader r m) => MonadReader r (ReaderT s m)' non esiste nemmeno ?! Perché? –