84 votes

Monades avec Java 8

Pour aider à comprendre ce qu'est une monade, quelqu'un peut-il donner un exemple en utilisant Java? Sont-ils possibles?

Les expressions lambda sont possibles en utilisant java si vous téléchargez la pré-version compatible JDK8 compatible lambda à partir d’ici http://jdk8.java.net/lambda/

Un exemple de lambda utilisant ce kit JDK est présenté ci-dessous. Quelqu'un peut-il fournir une monade relativement simple?

 public interface TransformService {
        int[] transform(List<Integer> inputs);
    }
    public static void main(String ars[]) {
        TransformService transformService = (inputs) -> {
            int[] ints = new int[inputs.size()];
            int i = 0;
            for (Integer element : inputs) {
                ints[i] = element;
            }
            return ints;
        };

        List<Integer> inputs = new ArrayList<Integer>(5) {{
            add(10);
            add(10);
        }};
        int[] results = transformService.transform(inputs);
    }
 

85voto

ms-tg Points 1087

Juste pour info:

Le projet de JDK8 Optionnel classe remplit les trois Monade lois. Voici un résumé en démontrant qu'.

Tout ce qu'il faut être une Monade est de fournir deux fonctions qui sont conformes aux trois lois.

Les deux fonctions:

  1. Placez une valeur monadique contexte

    • Haskell Peut-être: return / Just
    • Scala en Option: Some
    • Fonctionnel Java Option: Option.some
    • JDK8 en Option: Optional.of
  2. Appliquer une fonction monadique contexte

    • Haskell Peut-être: >>= (aka bind)
    • Scala en Option: flatMap
    • Fonctionnel Java Option: flatMap
    • JDK8 en Option: flatMap

Veuillez voir ci-dessus essentiel pour un java démonstration des trois lois.

REMARQUE: l'Une des principales choses à comprendre, c'est la signature de la fonction à appliquer dans monadique contexte: il prend de la valeur brute de type, et renvoie le type monadique.

En d'autres termes, si vous avez Optional<Integer>, les fonctions que vous pouvez passer à l' flatMap aurez la signature (Integer) -> Optional<U>U est un type de valeur qui ne doit pas être Integer, par exemple String:

Optional<Integer> maybeInteger = Optional.of(1);

// Function that takes Integer and returns Optional<Integer>
Optional<Integer> maybePlusOne = maybeInteger.flatMap(n -> Optional.of(n + 1));

// Function that takes Integer and returns Optional<String>
Optional<String> maybeString = maybePlusOne.flatMap(n -> Optional.of(n.toString));

Vous n'avez pas besoin d'aucune sorte de Monade Interface de code de cette façon, ou à penser de cette façon. En Scala, vous n'avez pas de code d'une Monade Interface (sauf si vous utilisez Scalaz bibliothèque...). Il semble que JDK8 permettra la Java des gens pour utiliser ce style de enchaînés monadique calculs ainsi.

Espérons que cela est utile!

Mise à jour: Blogué sur ce ici.

58voto

Faiz Points 8115

Java 8 aura lambdas; les monades sont une toute autre histoire. Ils sont assez dur à expliquer en programmation fonctionnelle (comme en témoigne le grand nombre de tutoriels sur le sujet en Haskell et la Scala).

Les monades sont une caractéristique typique de statiquement typé langages fonctionnels. Pour les décrire dans OO-parler, vous pouvez imaginer un Monad interface. Les Classes qui implémentent Monad serait alors appelé "monadique", à la condition que dans la mise en oeuvre Monad la mise en œuvre obéit à ce que l'on appelle la "monade lois". Le langage fournit ensuite quelques sucre syntaxique qui permet de travailler avec les instances de l' Monad classe intéressante.

Maintenant, Iterable en Java n'a rien à voir avec les monades, mais comme un exemple d'un type que le compilateur Java traite spécialement (l' foreach de la syntaxe qui est venu avec Java 5), pensez à ceci:

Iterable<Something> things = getThings(..);
for (Something s: things) {  /* do something with s */ }

Ainsi, alors que nous aurions pu utiliser Iterables' Iterator méthodes (hasNext et de l'entreprise) dans un vieux style for boucle, Java nous accorde ce sucre syntaxique comme un cas spécial.

Ainsi, tout comme les classes qui les implémentent Iterable et Iterator doit obéir à l' Iterator lois (Exemple: hasNext doit renvoyer false si il n'y a aucun élément suivant) pour être utile en foreach de la syntaxe -, il existe plusieurs monadique des classes qui serait utile avec un correspondant do notation (comme il est appelé en Haskell) ou Scala for de la notation.

So -

  1. Ce sont de bons exemples de monadique classes?
  2. Ce serait sucre syntaxique pour traiter avec eux ressembler?

Dans Java 8, je ne sais pas - je suis conscient de la lambda notation, mais je ne suis pas au courant d'autres sucre syntaxique, donc je vais vous donner un exemple dans une autre langue.

Les monades souvent servir de conteneur des classes (les Listes sont un exemple). Java a déjà java.util.List qui n'est évidemment pas monadique, mais ici, c'est de Scala:

val nums = List(1, 2, 3, 4)
val strs = List("hello", "hola")
val result = for { // Iterate both lists, return a resulting list that contains 
                   // pairs of (Int, String) s.t the string size is same as the num.
  n <- nums        
  s <- strs if n == s.length 
} yield (n, s)
// result will be List((4, "hola")) 
// A list of exactly one element, the pair (4, "hola")

Qui est (à peu près) sucre syntaxique pour:

val nums = List(1, 2, 3, 4)
val strs = List("hello", "hola")
val results = 
nums.flatMap( n =>                 
  strs.filter(s => s.size == n).   // same as the 'if'
       map(s => (n, s))            // Same as the 'yield'
)
// flatMap takes a lambda as an argument, as do filter and map
// 

Cela montre une caractéristique de la Scala, où les monades sont exploitées pour fournir des interprétations de la liste.

Ainsi, un List de la Scala est une monade, parce qu'il obéit à Scala, à la monade lois, qui stipulent que tous les monade implémentations doivent avoir conformes flatMap, map et filter méthodes (si vous êtes intéressés par les lois, les "Monades sont les Éléphants" entrée de blog est la meilleure description que j'ai trouvé à ce jour). Et, comme vous pouvez le voir, les lambdas (et HoF) sont absolument nécessaires mais non suffisants pour faire ce genre de chose utile en pratique.

Il y a un tas de utile monades outre le conteneur-ish que de bien. Ils ont toutes sortes d'applications. Mon préféré doit être l' Option monade en Scala (l' Maybe monade en Haskell), qui est un wrapper type qui apporte de la valeur null à la sécurité: la Scala API page pour l' Option monade a un exemple très simple d'utilisation: http://www.scala-lang.org/api/current/scala/Option.html En Haskell, les monades sont utiles dans la représentation de IO, comme un moyen de contourner le fait que les non-monadique du code Haskell a durée indéterminée ordre d'exécution.

Avoir des lambdas est un premier petit pas dans le monde de la programmation fonctionnelle; monades nécessitent à la fois de la monade convention et un assez grand ensemble de utilisable monadique types, ainsi que le sucre syntaxique pour rendre le travail avec eux amusant et utile.

Depuis la Scala est sans doute le langage le plus proche de Java qui permet également (monadique) Programmation Fonctionnelle, regarde cette Monade tutoriel pour Scala si vous êtes (encore) intéressé: http://james-iry.blogspot.jp/2007/09/monads-are-elephants-part-1.html

Une rapide recherche sur google montre qu'il y a au moins une tentative de le faire en Java: https://github.com/RichardWarburton/Monads-in-Java -

Malheureusement, en expliquant les monades en Java (même avec des lambdas) est aussi difficile que l'explication complète de la programmation orientée Objet en C ANSI (au lieu de C++ ou Java).

12voto

Muzietto Points 102

Même si les monades peuvent être mises en œuvre en Java, tout calcul impliquant eux est condamné à devenir un désordre mélange de médicaments génériques et des accolades.

Je dirais que Java est certainement pas la langue à utiliser pour illustrer leur travail ou à l'étude de leur sens et de l'essence. À cette fin, il est de loin préférable d'utiliser du Javascript ou de payer une partie de la différence de prix et d'apprendre Haskell.

De toute façon, je suis de signalisation vous que j'ai juste mis en place un état de monade à l'aide de la nouvelle Java 8 lambdas. C'est certainement un projet de compagnie, mais il fonctionne sur une base non négligeable de cas de test.

Vous pouvez trouver qu'il a présenté à http://wp.me/pY4ph-brmais je vais vous donner quelques détails ici.

Un état de monade est essentiellement une fonction à partir d'un état à un couple (état,le contenu). Vous avez l'habitude de donner à l'état un générique de type S et le contenu d'un type générique A.

Parce que Java n'a pas de paires que nous avons de les modéliser à l'aide d'une classe spécifique, appelons-la Scp (état-contenu paire), qui dans ce cas sera de type générique Scp<S,A> et un constructeur new Scp<S,A>(S state,A content). Après cela, nous pouvons dire que la fonction monadique de type

java.util.function.Function<S,Scp<S,A>>

qui est un @FunctionalInterface. C'est-à-dire que sa seule et unique méthode abstraite ne peut être invoquée sans la nommer, en passant d'une expression lambda avec le type de droit.

La classe StateMonad<S,A> est principalement un wrapper autour de la fonction. Son constructeur ne peut être invoquée par ex. avec

new StateMonad<Integer, String>(n -> new Scp<Integer, String>(n + 1, "value"));

L'état de monade magasins de la fonction comme une variable d'instance. Il est alors nécessaire de fournir une méthode pour y accéder et de le nourrir à l'état. J'ai décidé de l'appeler s2scp ("l'état-contenu paire").

Pour terminer la définition de la monade, vous devez fournir une unité (aka retour) et bind (aka flatMap) de la méthode. Personnellement, je préfère préciser l'unité statique, alors que la liaison est un membre de l'instance.

Dans le cas de l'état de monade, l'unité doit être la suivante:

public static <S, A> StateMonad<S, A> unit(A a) {
    return new StateMonad<S, A>((S s) -> new Scp<S, A>(s, a));
}

alors que bind (en tant que membre de l'instance) est:

public <B> StateMonad<S, B> bind(final Function<A, StateMonad<S, B>> famb) {
    return new StateMonad<S, B>((S s) -> {
        Scp<S, A> currentPair = this.s2scp(s);
        return famb(currentPair.content).s2scp(currentPair.state);
    });
}

Vous remarquez que la liaison doit introduire un générique de type B, parce que c'est le mécanisme qui permet le chaînage de l'hétérogène, de l'état des monades et donne à cette et toutes les autres monade la capacité remarquable de déplacer le calcul de type de type.

J'avais arrêter ici avec le code Java. Le complexe des choses est dans le GitHub du projet. Par rapport aux précédentes versions de Java, les lambdas de supprimer un certain nombre d'accolades, mais la syntaxe est encore assez alambiquée.

Juste en aparté, je suis en montrant comment le même état monade code peut être écrit dans d'autres langages génériques. Dans le cas de la Scala, bind (qui dans ce cas doit être appelé flatMap) se lit comme

def flatMap[A, B](famb: A => State[S, B]) = new State[S, B]((s: S) => {
  val (ss: S, aa: A) = this.s2scp(s)
  famb(aa).s2scp(ss)
})

alors que la liaison en Javascript est mon préféré; 100% fonctionnelle, maigre et moyenne, mais -bien sûr - sans type:

var bind = function(famb){
    return state(function(s) {
        var a = this(s);
        return famb(a.value)(a.state);
    });
};

<éhontée> Je suis à la coupe un peu de coins ici, mais si vous êtes intéressé par les détails, vous les trouverez sur mon blog WP.</sans vergogne>

5voto

Morteza Adi Points 585

la seule façon de comprendre les monades est par l'écriture d'un tas de combinateur bibliothèques, remarquant l'résultant de la duplication, puis la découverte de vous-même que les monades vous permettent de factoriser cette duplication. En découvrant cela, tout le monde construit une certaine intuition de ce qu'est une monade est... mais cette intuition n'est pas le genre de chose que vous pouvez communiquer à quelqu'un d'autre directement – il semble que tout le monde doit passer par la même expérience de la généralisation de monades à partir de quelques exemples concrets de combinateur de bibliothèques. cependant

ici, j'ai trouvé certains matériaux pour en savoir Mondas.

l'espoir d'être utile pour vous aussi.

codecommit

james-iri.blogspot

debasishg.blogspot

2voto

codemiller Points 563

Ce blog donne des instructions étape par étape exemple de comment vous pouvez mettre en œuvre une Monade type (interface) en Java, et ensuite l'utiliser pour définir la monade Peut-être, comme une application pratique.

Ce post explique qu'il y a une monade construit dans le langage Java, en insistant sur le point que les monades sont plus fréquents que beaucoup de programmeurs peuvent penser et que les codeurs souvent par inadvertance, les réinventer.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X