2017-08-15 7 views
6

Je regarde the documentation pour le transformateur monade Reader monad et ReaderT.Quel est l'objectif de * dans le transformateur Monad ReaderT?

Les définitions pertinentes sont:

newtype ReaderT k r m a :: forall k. * -> (k -> *) -> k -> * 
type Reader r = ReaderT * r Identity 

Je ne comprends pas ce que l'* font dans les définitions. En particulier, je tente de dériver une nouvelle monade de ReaderT avec IO comme monade de base et une contrainte de classe sur la valeur r. Je ne suis pas sûr pourquoi il y a une quatrième entrée à ReaderT (k) et ce que le Reader fait avec cette valeur quand il met un * dans cette position.

+6

Remarque que le code source de 'ReaderT' est' newtype ReaderT rma = ReaderT {runReaderT :: r -> ma} '. Le 'k' est seulement généré dans la documentation par Haddock pour souligner la poly-gentillesse de' ReaderT' ('-XPolyKinds' est activé dans le module où il est défini). – Alec

+2

"Je tente de dériver une nouvelle monade de ReaderT avec IO comme monade de base et une contrainte de classe sur la valeur r" - alors que cela risque de causer plus de problèmes qu'elle n'en résout (le placement d'une contrainte sur le 'r' valeur, pas la dérivation d'un nouveau type de 'ReaderT' avec' m' instancié à 'IO') Je ne vois pas pourquoi cela serait entravé par la définition polykinded de' ReaderT'. Comme l'indique @Alec, le paramètre 'k' est un artefact de haddock - en réalité, il est entièrement implicite, et vous pouvez prétendre que' ReaderT :: (* -> *) -> * -> * '(parce qu'il le fait en effet avoir ce type). – user2407038

+0

@ user2407038 et nicolas Vous avez tous les deux raison. La contrainte appartenait et est maintenant placée sur une déclaration d'instance et non sur la définition de monade. –

Répondre

5

* est le genre de types avec des valeurs: il signifie des choses comme Int, etc .. List Int

forall k signifie k est pas nécessairement de ce genre. il représente tout type de types, considérés comme des choses statiques que vous pouvez déclarer et manipuler, mais qui ne sont pas nécessairement associés aux valeurs d'exécution. Un exemple de ceci est quand vous voulez 'décorer' un autre type avec des informations supplémentaires: le type de broderie n'a aucune raison d'avoir une sorte de valeur attachée, c'est une information "pure", à un type brodé (qui a généralement valeurs)

Plus simplement ici, vous pouvez voir que Reader tout se spécialise à * et m est spécialisée à la Identity monade. C'est là que vous voudriez que votre monade IO soit. En ce qui concerne les contraintes, il est préférable de ne pas le spécifier dans le type lui-même. Lors de l'utilisation, lorsque vous utilisez une méthode particulière attachée à la classe de type, il sera ajouté à la volée. En effet, il n'y a aucune raison pour laquelle les expressions écrites qui n'utilisent pas de méthode devraient être surchargées en demandant à leurs appelants de les fournir.

(Sauf si vous avez une très bonne raison, par déduisant d'autres cas, comme dans Dict où vous capturez un témoin de classe de types comme valeur d'exécution avec un GADT, mais qui est sans doute pas ce que vous voulez faire)

+0

Vous avez raison. La contrainte appartenait et est maintenant placée sur une déclaration d'instance et non sur la définition de monade. –