2017-09-08 5 views
3

je tente d'écrire un opérateur de comparaison plus-que-égal pour deux lens getters avec le typegetter de lentille Haskell qui compare les valeurs de deux lentilles getters

(.>=.) :: Ord a => Getting a s a -> Getting a s a -> Getting Bool s Bool 

J'ai une solution de travail pour un getter sur le côté gauche et une valeur sur le côté droit (pas . sur le côté droit de l'opérateur .>=)

J'ai essayé

left .>=. right = (>=) <$> use left <*> use right 

mais il a le type

(.>=.) :: (Ord a, MonadState s f) => Getting a s a -> Getting a s a -> f Bool 

Comment puis-je obtenir le type de rendement souhaité Getting Bool s Bool au lieu de f Bool?

Répondre

5

Vous êtes proche avec ceci:

λ> left .>=. right = (>=) <$> use left <*> use right 
(.>=.) :: 
    (Ord a, Control.Monad.State.Class.MonadState s f) => 
    Getting a s a -> Getting a s a -> f Bool 

Tout d'abord, utilisez view au lieu de use; use est pour obtenir de l'état (d'où la contrainte MonadState), ce qui ne semble pas pertinent ici.

λ> left .>=. right = (>=) <$> view left <*> view right 
(.>=.) :: 
    (Ord a, Control.Monad.Reader.Class.MonadReader s f) => 
    Getting a s a -> Getting a s a -> f Bool 

Cela vous donne une fonction (MonadReader s f => f Bool à s -> Bool est spécialisée), maintenant vous devez en faire un Getting avec to.

λ> left .>=. right = to $ (>=) <$> view left <*> view right 
(.>=.) :: 
    (Ord a, Contravariant f, Profunctor p) => 
    Getting a s a -> Getting a s a -> Optic' p f s Bool 

(Et (Contravariant f, Profunctor p) => Optic' p f s Bool à Getting Bool s Bool se spécialise, donc ce que vous voulez.)