Sì! La prima cosa da notare è che something
deve avere il tipo Setter
(e, senza perdita di generalità, Setter'
). Per quanto riguarda il tipo usiamo i buchi.
maybeTContents :: Setter' (MaybeT m a) a
maybeTContents =
_Wrapped . _ . _Just
GHC ci dice che vuole digitare Settable f => (Maybe a -> f (Maybe a)) -> (m (Maybe a) -> f (m (Maybe a))
per il buco.
Con un viaggio su Hackage riconosciamo questo tipo come Setter' (m (Maybe a)) (Maybe a)
. Quindi, risolvendo u ~ Maybe a
, possiamo riformulare la domanda più in generale: esiste un setter che si unifica sia con Setter' [u] u
sia con Setter' (Reader u) u
?
Ma, sia come []
e Reader
hanno casi functor possiamo rivolgerci a un assoluto classico di un setter mapped
, the setter heard around the world. mapped
ha il tipo mapped :: Functor f => Setter (f a) (f b) a b
- si scopre quando è disponibile un'istanza di functor che mapped = sets fmap
è il valore che obbedisce a tutte le leggi setter.
Possiamo vedere in azione qui:
% stack ghci
GHCi, version 7.10.3: http://www.haskell.org/ghc/ :? for help
Ok, modules loaded: none.
λ> import Control.Lens
λ> import Control.Monad.Trans.Maybe
λ> import Control.Monad.Trans.Reader
λ> MaybeT [Just 1, Nothing, Just 2, Nothing, Just 3] & _Wrapped . mapped . _Just .~ 100
MaybeT [Just 100,Nothing,Just 100,Nothing,Just 100]
λ> data A = A
λ> data B = B
λ> :t MaybeT (ReaderT (\r -> Identity (Just A)))
MaybeT (ReaderT (\r -> Identity (Just A)))
:: MaybeT (ReaderT r Identity) A
λ> :t MaybeT (ReaderT (\r -> Identity (Just A))) & _Wrapped . mapped . _Just .~ B
MaybeT (ReaderT (\r -> Identity (Just A))) & _Wrapped . mapped . _Just .~ B
:: MaybeT (ReaderT r Identity) B
Poiché non vi era alcuna Show
istanza per ReaderT
il meglio che potessi fare per illustrare che il setter ha lavorato è stato quello di generare due tipi di marca-spankin'-nuovi A
e B
.
Questa domanda è fantastica, perché è al centro della motivazione alla base del pacchetto lens
. Dato fmapDefault
dal mondo Traversable
, è possibile correggere il traversable per essere Identity
per scrivere over
. È quindi possibile scrivere l'inverso di over
, sets
, ad esempio over . sets = id
e sets . over = id
. Siamo quindi costretti a concludere che mapped = sets fmap
è un setter naturale che obbedisce al tipo di leggi che vogliamo per i setter, uno dei più importanti è che mapped . mapped . mapped
compone con (.)
. Il resto di lens
segue presto.
@haoformayor per quanto riguarda la modifica del titolo - 'MaybeT' è solo un esempio di quello che sto cercando. speriamo che il nuovo titolo spieghi meglio cosa sto cercando – yairchu
Vedi anche https://github.com/ekmett/lens/wiki/Varying-lens-properties-by-instance – phadej