lentilles, fclabels, données accesseur - la bibliothèque de la structure d'accès et de mutation est mieux
Il y a au moins trois bibliothèques populaires pour accéder et manipuler des champs des enregistrements. Ceux que je connais sont: les données-accesseur, fclabels et les lentilles.
Personnellement j'ai commencé avec les données de l'accesseur et je suis en utilisant maintenant. Toutefois récemment sur haskell-café, il y avait un avis de fclabels être supérieur.
Donc je suis intéressé par la comparaison de ces trois (et peut-être plus) des bibliothèques.
- À compter d'aujourd'hui,
lens
le paquet de riches fonctionnalités et de la documentation, donc si vous n'avez pas l'esprit de sa complexité et ses dépendances, c'est le chemin à parcourir.
Vous devez vous connecter pour publier un commentaire.
Il y a au moins 4 bibliothèques que je suis conscient de fournir des lentilles.
La notion d'une lentille est qu'il offre quelque chose d'isomorphe à
fournissant deux fonctions: un getter et un setter
soumis aux trois lois:
D'abord, que si vous mettez quelque chose, vous pouvez le sortir
Que l'obtention de la deuxième, puis la configuration ne change pas la réponse
Et la troisième, en mettant deux fois, c'est la même chose que de mettre une fois, ou plutôt, que la deuxième de mettre les victoires.
Noter que le type de système n'est pas suffisant pour vérifier ces lois pour vous, alors vous devez vous assurer que vous-même n'importe quelle lentille de mise en œuvre que vous utilisez.
La plupart de ces bibliothèques fournissent également un tas d'extra combinators sur le dessus, et généralement une certaine forme de modèle haskell machines pour générer automatiquement des lentilles pour les champs de simples types d'enregistrement.
Avec cela à l'esprit, nous pouvons nous tourner vers les différentes implémentations:
Implémentations
fclabels
fclabels est peut-être le plus facilement motivé à propos de l'objectif des bibliothèques, parce que son
a :-> b
peuvent être traduits directement du type ci-dessus. Il fournit un Catégorie exemple pour(:->)
qui est utile car il permet de composer des lentilles. Il fournit également un lawlessPoint
type qui généralise la notion d'objectif utilisé ici, et certains de plomberie pour traiter isomorphisms.Un obstacle à l'adoption de
fclabels
est que le paquet inclut le modèle-haskell de plomberie, de sorte que le paquet n'est pas Haskell 98, et il exige aussi l' (assez controversée)TypeOperators
extension.de données accesseur
[Edit:
data-accessor
n'est plus à l'aide de cette représentation, mais a déménagé à une forme semblable à celle dedata-lens
. Je vais garder ce commentaire, si.]données accesseur est un peu plus populaire que
fclabels
, en partie parce qu'il est Haskell 98. Cependant, le choix de la représentation interne me fait vomir dans ma bouche un petit peu.Le type
T
il utilise pour représenter une lentille est à l'intérieur défini commePar conséquent, afin de
get
la valeur d'un objectif, vous devez soumettre une valeur non définie pour le 'a' argument! Ce qui me frappe comme un incroyablement laid et ad hoc de mise en œuvre.Cela dit, Henning a inclus le modèle-haskell plomberie pour automatiquement générer les accesseurs pour vous dans un groupe séparédonnées accesseur-modèle' paquet.
Il a l'avantage d'une décemment grand ensemble de paquets qui utilisent déjà, étant Haskell 98, et fournissant la
Category
exemple, si vous ne payez pas attention à ce que la saucisse est faite, ce package est en fait assez raisonnable de choix.lentilles
Ensuite, il y a la lentilles paquet, qui observe que l'objectif est de fournir un état de monade homomorphism entre deux état monades, par definining lentilles directement comme tels monade homomorphisms.
Si elle a effectivement pris la peine de fournir un type pour ses lentilles, ils ont un rang-2 type:
Comme un résultat, je n'aime pas cette approche, car elle inutilement les ricains vous de Haskell 98 (si vous voulez un type de fournir à vos lentilles dans l'abstrait) et vous prive de la
Category
exemple pour les verres, ce qui vous permet de composer avec.
. La mise en œuvre nécessite également multi-paramètre type de classes.Note, toutes les autres lentilles bibliothèques mentionnés ici de fournir quelques combinator ou peut être utilisé pour fournir ce même état focalisation effet, si rien n'est gagné par l'encodage de vos lentilles directement dans ce mode.
En outre, le côté-conditions énoncées au début n'ont pas vraiment de jolie expression sous cette forme. Comme fclabels' c'est un modèle haskell méthode pour la génération automatique de lentilles pour un type d'enregistrement directement dans le paquet principal.
En raison de l'absence de
Category
exemple, le baroque de l'encodage et de l'exigence de modèle-haskell dans le paquet principal, c'est ma préférée au moins de la mise en œuvre.données de la lentille
[Edit: Comme de la version 1.8.0, ils ont déménagé de la comonad-transformateurs de paquet de données-lens]
Mon
données-lens
paquet fournit des lentilles en termes de Magasin comonad.où
Élargi c'est l'équivalent de
Vous pouvez afficher ce que l'affacturage l'argument commun de le getter et le setter retourner une paire composée de la suite de la récupération de l'élément, et un setter pour mettre une nouvelle valeur. Cette offre le calcul de l'avantage que le "setter" ici peut recycler une partie du travail permet d'obtenir la valeur, ce qui rend plus efficace "modifier", fonctionnement que dans le
fclabels
définition, en particulier lorsque les accesseurs sont enchaînés.Il ya aussi une belle justification théorique de cette représentation, parce que le sous-ensemble de 'Objectif', des valeurs qui satisfont les 3 lois déclaré au début de cette réponse sont précisément les objectifs pour lesquels le enveloppés fonction est un "comonad coalgebra" pour le magasin comonad. Cela transforme 3 poilu lois pour une lentille
l
à 2 joliment pointfree équivalents:Cette approche a d'abord été constaté et décrit dans Russell O'Connor
Foncteur
àObjectif
Application
àBiplate
: présentation de Multidisque à bain d'huile et a été blogué sur basé sur un preprint par Jeremy Gibbons.Il comprend également un certain nombre de combinators pour travailler avec des objectifs strictement et un peu de bouillon de lentilles pour des récipients, tels que
Data.Map
.Donc les lentilles dans
data-lens
forme d'unCategory
(contrairement à lalenses
emballage), sont Haskell 98 (contrairement àfclabels
/lenses
), sont sain d'esprit (contrairement à l'extrémité arrière dedata-accessor
) et de fournir un peu plus d'une mise en œuvre efficace,données-lens-fd
fournit les fonctionnalités pour travailler avec MonadState pour ceux qui sont prêts à sortir de Haskell 98, et le modèle-haskell machines est maintenant disponible viadonnées-lens-template
.Mise À Jour 6/28/2012: Autre Objectif De La Mise En Œuvre Des Stratégies De
Isomorphisme Lentilles
Il y a deux autres objectifs codages vaut la peine d'examiner. Le premier donne une belle façon théorique, à la vue d'un objectif comme un moyen de briser une structure dans la valeur du champ, et "tout le reste'.
Donné un type pour isomorphisms
tels que des membres valides satisfaire
hither . yon = id
, etyon . hither = id
On peut représenter un objectif avec:
Ce sont surtout utiles comme une façon de réfléchir sur le sens de lentilles, et nous pouvons les utiliser comme un outil de raisonnement pour expliquer les autres lentilles.
van Laarhoven Lentilles
Nous pouvons modéliser des objectifs tels qu'ils peuvent être composées avec
(.)
etid
, même sansCategory
exemple en utilisantque le type de nos objectifs.
Puis de définir un objectif est aussi simple que:
et vous pouvez vérifier par vous-même que la fonction de la composition de la lentille de la composition.
J'ai récemment écrit sur la façon dont vous pouvez généraliser van Laarhoven lentilles pour obtenir la lentille familles qui peuvent changer les types de champs, tout en généralisant cette signature à
Cela a pour conséquence regrettable que la meilleure façon de parler de lentilles est d'utiliser le rang 2 de polymorphisme, mais vous n'avez pas besoin d'utiliser cette signature directement lors de la définition des objectifs.
La
Lens
j'ai défini ci-dessus pour_2
est en fait unLensFamily
.J'ai écrit une bibliothèque qui comprend des lentilles, des lentilles de familles, et d'autres généralisations y compris les getters, setters, les plis et les traversals. Il est disponible sur le hackage comme le
objectif
paquet.Encore une fois, un grand avantage de cette approche est que les responsables de la bibliothèque peut effectivement créer des lentilles dans ce style dans vos bibliothèques sans encourir aucune lentille de la bibliothèque de dépendance que ce soit, par la simple fourniture de fonctions de type
Functor f => (b -> f b) -> a -> f a
, de leurs types " a " et "b". Cela réduit considérablement le coût de l'adoption.Puisque vous n'avez pas besoin d'utiliser effectivement le package de définir de nouveaux objectifs, il faut beaucoup de pression sur mon préoccupations antérieures sur la tenue à la bibliothèque Haskell 98.
:->
fclabels
a le typePoint
est de fournir une composition parallèle avec sesApplicative
exemple, à côté de la composition séquentielle que leCategory
instance deLens
fournit.fmapL
envisager de l'utiliser pour lever toute vieilleLens
dans leMaybe
Applicative
. Lorsque vous allez mettreJust foo
enNothing
le résultat resteNothing
, donc quand vous allez pour obtenir la valeur de ce champ avec votre objectif, vous obtenezNothing
plutôt que votreJust foo
dos et de la première loi échoue.fmapL
crée seulement bon les lentilles avec les types de conteneurs avec un nombre fixe de "trous", commeVec n
, qui ont une fermeture éclair-commeApplicative
instance. Toutefois, l'objectif qui est créé est le plus naturel possible pourMaybe
, dans un sens vague qui devrait sans doute être plus concret.data-accessor
, et puis j'ai passé plus de Henning et a cessé de payer attention. Lea -> r -> (a,r)
représentation me fait aussi mal à l'aise, et mon original à la mise en œuvre a été, tout comme votreLens
type. Heeennnninngg!!repLens
fournir le plus sûrfmapL
représentable-foncteursdata-accessor
est plus précis: depuis 0.2.1.8 il utilisenewtype T r a = Cons {decons :: r -> (a, a -> r)}
._2 f (a,b) = (,) a <$> f b
?newtype T r a = Cons {decons :: r -> (a, a -> r)}
, qui est à peu près isomorphe à celle utilisée dans les données de la lentille.