8
votes

Aide à l'écriture de "The Colist Monad" (Exercice d'un papier d'introduction d'idiomes)

Je lis la lecture de Conor McBride et de la perle fonctionnelle de Ross Paterson: Programmation applicative avec effets: "(The nouvelle version , avec" idiomes "dans le titre). J'ai un peu de difficulté avec l'exercice 4, qui est expliqué ci-dessous. Toute astuce serait très appréciée (surtout: devrais-je commencer à écrire fmap et joindre ou retour et >> = ?).

instruction problématique

Vous souhaitez créer un instance monade [] xxx

et ap = zapp .

Fonctions de la bibliothèque standard

comme sur p. 2 du papier, AP applique une valeur de fonction monadique à une valeur monadique. xxx

J'ai développé ceci en notation canonique à, xxx

la fonction spécifique à la liste zapp ("zippy application") applique une fonction d'une liste à une valeur correspondante dans une autre, à savoir xxx

mes difficultés

Notez que sous la forme expansée, MF :: m (a -> b) est une liste de fonctions < Code> [(A -> B)] dans notre cas. Donc, dans la première application de >>> = , nous avons xxx

mu = (\ f -> (MS >> = \ s -> retour (fs))) . Maintenant, nous pouvons appeler fs >> = mu comme sous-programme, mais cela ne sait pas de supprimer le premier élément de MS . (Rappelons que nous voulons que la liste résultante soit [F1 S1, F2 S2, ...]. J'ai essayé de pirater quelque chose mais ... comme prévu, cela ne fonctionnait pas ... aucune aide serait très appréciée. < / p>

Merci d'avance!

Editer 1

Je pense que je l'ai eu pour travailler; d'abord, j'ai réécrit AP avec fmap et rejoindre comme utilisateur "COMONAD" suggéré.

Mon saut de foi supposait que fmap = mapper . Si quelqu'un peut expliquer comment Pour y arriver, je l'apprécierais beaucoup. Après cela, il est clair que rejoindre fonctionne dans la liste des listes "COMONAD" suggéré, et devrait être la diagonale, \ x - > zipwith (((!!). OLL) x [0 ..] . Mon code complet est ceci: xxx

Espérons que c'est bien (semble être le "Solution" sur p. 18 du papier) ... Merci pour l'aide, tout le monde!


1 commentaires

Concernant FMAP : Les lois applicatifs incluent l'identité pure f <*> x = f <$> x . Vous devriez être capable d'afficher fmap comme étant mappe en utilisant ceci. Et oui, rejoindre prend la diagonale des listes imbriquées - en tant qu'exercice de suivi, vous pouvez essayer de montrer comment la diagonale étant mal définie sur des listes de longueurs différentes enfreint les lois monad.


3 Réponses :


12
votes

hm. Je ne peux pas m'empêcher de penser que cet exercice est un peu injuste comme présenté.

Exercice 4 (Colist Monad)

Bien que répéter et zapp ne sont pas le renvoyer et ap de l'habituel monad [] instance, ils ne sont pas moins le renvoyer et ap d'une monade alternative, plus adaptée à L'interprétation coindante de [] . Quel est le Join :: [[[x]] → [x] de cette monade?

Commentaire sur l'efficacité relative de cette monade AP et notre zapp .

Premièrement, je suis assez certain que l'instance monad en question est non valide pour [] en général . Quand ils disent "l'interprétation coindante", je soupçonne que cela fait référence à listes infinies . L'instance est réellement valable pour les listes finies dans certains cas, mais pas pour les listes arbitraires en général.

C'est donc votre première, très générale, indice - pourquoi une instance monad ne serait-elle valable que pour certaines listes, particulièrement infinies?

Voici votre deuxième indice: FMAP et retour est trivial donné d'autres définitions plus tôt dans le document. Vous avez déjà retour ; fmap n'est que légèrement moins évident.

En outre, (>> =) a une implémentation facile en termes d'autres fonctions, comme avec tout monad , qui laisse rejoindre comme le creux de la matière. Dans la plupart des cas, (>> =) est plus naturel pour la programmation avec, mais rejoindre est plus fondamentalement fondamental et dans ce cas, je pense, plus simple d'analyser. Je recommande donc de travailler sur cela et d'oublier (>> =) pour l'instant. Une fois que vous avez une implémentation, vous pouvez revenir en arrière et reconstruire (>> =) et vérifier les lois monad pour vous assurer que tout fonctionne correctement.

Enfin, supposons un instant que vous avez fmap disponible, mais rien d'autre. Valeurs données avec type [A -> B] et [A] , vous pouvez les combiner pour obtenir quelque chose de type [[B] . Le type de rejoindre est ici [[[a]] -> [a] . Comment pourriez-vous écrire rejoindre de telle sorte que vous obtenez le même résultat ici que vous iriez à partir d'utiliser zapp sur les valeurs d'origine? Notez que la question sur l'efficacité relative est, ainsi qu'une question, une indice quant à la mise en œuvre.


6 commentaires

@camccann: Je ne suis pas clair sur un point. Si l'interprétation de cotination fait référence à des listes infinies (je suis d'accord c'est probablement), alors ne serait pas répéter et zapp former réellement une monade qui n'est pas nonité à ladite interprétation cofinante ? C'est le cas de ZIPLIST , qui n'a pas d'instance de monad valide. Quoi qu'il en soit, je soupçonne que les auteurs ont choisi cet exemple pour indiquer que les foncteurs applicatifs sont utiles en partie parce qu'ils sont plus généraux que les monads (honte sur moi, je n'ai pas encore lu le papier).


@John L: errrh ... Vous avez raison que cela équivaut à ZIPLIST , mais vous avez manqué quelques autres choses, et je ne peux pas vraiment clarifier sans gâcher la réponse à l'exercice Gatorotitro travaille sur. : [


@CamCcan: J'avais peur de ça. Je vais juste lire le papier et espérer que cela remplit les détails.


@John L: Probablement pas - je ne l'ai probablement pas écoulée (après avoir lu la version plus ancienne auparavant) mais je ne pense pas que cette monade particulière est venue à l'extérieur de l'exercice, ce que j'ai cité complet. Cela dit, c'est une bonne lecture, alors aucun mal à le donner! Mais si vous préférez une explication plus directe que de travailler vous-même à travers l'exercice vous-même, n'hésitez pas à me contacter par courrier électronique.


@CamCcann: Vous avez tout à fait raison, le papier était inutile à cet effet (bien que sinon une bonne lecture!). Cependant, j'ai remarqué que j'ai mal interprété l'exercice et je pensais à une liste régulière monade, pas au colon monad. Cela a effacé bien.


@John L: Oui, c'est certainement très différent de la norme joindre pour les listes! La comparaison d'efficacité est également intéressante - elle concerne ce que je pouvais appeler la différence "philosophique" entre applicatif et monad et des différences de performance similaires peuvent exister pour d'autres fonctions-- Il semble que je me souvienne d'entendre en entendant des combinaisons d'analyseurs, par exemple.



4
votes

La définition complète minimale d'une monade est soit fmap + retour + joindre ou retour + + (>> =) . Vous pouvez implémenter celui avec l'autre: xxx

maintenant, la mise en œuvre de AP peut être réécrit en termes de joindre et FMAP : xxx

dans l'exercice, la sémantique de FMAP et retour et AP est donné. Le reste sera évident, dès que vous examinerez un exemple: xxx


2 commentaires

Juste curieux, flip fmap a-t-il un sens catégorique? (S'il est juste d'interpréter fmap en tant que foncteur de tri?)


@GatoAttiGrado: Cela a du sens dans la mesure où les endofuncteurs de la catégorie des types de haskell sont équivalents aux familles de morphismes de la catégorie. En termes catégoriques, Join :: M (MA) -> MA est une transformation naturelle et FMAP :: (A -> B) -> (FA -> FB) est une cartographie des fonctions entre les flèches dans des catégories "différentes" ... mais Haskell aplatit tout ce qui est de type morphisme en juste (->) .



11
votes

Je pensais juste que je devrais clarifier que la version avec des exercices et des "idiomes" dans le titre est un brouillon plutôt antérieur du document qui a finalement été apparu dans JFP. À ce moment-là, j'ai pensé à tort que les colis (par lesquels je veux dire peut-être des listes d'infinies, éventuellement finis) étaient une monade de manière à zapper: il existe un candidat plausible pour la jointure (alluitée dans d'autres réponses) mais Jeremy Gibbons était assez gentille de nous signaler que cela ne satisfait pas aux lois monad. Les contre-échappes impliquent des listes "déchiquetées" des listes avec des longueurs finies variables. De manière correspondante, dans l'article du JFP, nous sommes restés corrigés. (Nous étions plutôt heureux de cela, car nous aimons trouver des foncteurs applicatifs dont (<*>) n'est pas l'AP d'une monade.)

Les listes nécessairement infinies (c'est-à-dire flux ), en excluant les cas en lambeaux, forment effectivement une monade dont AP se comporte comme Zapp. Pour une indice, notez que le flux X est isomorphe à NAT -> x.

Mes excuses pour la confusion. Il est parfois dangereux de laisser des brouillons anciens et inachevés (remplissez d'erreurs) mentent (ha ha) sur le Web.


4 commentaires

Merci! Je profite de la version plus ancienne ayant des exercices, cependant :)


Oho! Cela fait plutôt plus de sens maintenant. Cela me semblait très étrange que l'exercice ne donnait aucune indication que la monade suggérée n'était valable que sur des listes de longueur égale.


@camccann qui me rappelle: tous les constructeurs de type vecteur de longueur fixe sont monadiques, par une construction similaire (y compris mon préféré, les vecteurs de la longueur zéro).


@Conor McBride: Eh bien, tout ce qui est en forme fixe peut être combiné à l'élément, qui sont toutes la même famille brute de monades qui ont souvent plus de sens comme applicatif . Vous pouvez "zip" arbres au lieu de substituer aux feuilles, par exemple. Interprétation a -> b comme une structure de B s dont la forme est donnée par A , le lecteur monade est l'un d'entre eux aussi. Il y a une sorte d'abstraction bien rangée qui généraliste tout le lot ...