2017-09-20 4 views
1

Étant donné:`then` sur Kleisli de différents types d'entrée?

import scalaz._, Scalaz._ 
import scalaz.concurrent.Task 

case class AppConfig(x: Int, y: String) 

val x = Kleisli[Task, Int, Boolean] { 
    case i: Int => if (i === 42) Task.now(true) else Task.now(false) 
} 

val y = Kleisli[Task, String, Unit] { 
    case s: String => Task.delay { println(s"$s was here") } 
} 

Je ne peux pas appeler x >> y en raison de la compilation a échoué:

scala> x >> y 
<console>:21: error: type mismatch; 
found : scalaz.Kleisli[scalaz.concurrent.Task,String,Unit] 
required: scalaz.Kleisli[scalaz.concurrent.Task,Int,?] 
     x >> y 
      ^

En conséquence, est-il raisonnable de changer x et types de y de Kleisli[Task, Int, Boolean] et Kleisli[Task, String, Boolean]-Kleisli[Task, AppConfig, Boolean]?

Sinon, veuillez suggérer une meilleure alternative et votre justification.

Répondre

2

Je pense que ce que vous recherchez est

x *** y 

qui vous donnera Kleisli[Task, (Int, String), (Boolean, Unit)].

Le *** provient de la syntaxe Arrow, et des moyens composition parallèle (par opposition à la composition séquentielle de >>= ou >>).

1

Voici ce qui se passe: puisque dans Scalaz Kleisli[M, A, B] peut être interprété comme la fonction Scala A => M[B], il y a une instance de lecteur monad intégrée, qui est utilisée dans ce cas. Lecteur monad est défini sur les fonctions R => M[A] lecture de type fixe R. Vous avez donc besoin de saisir les types de flèches Kleisli pour les utiliser, ce qui n'est pas le cas. Composition Kleisli, >=>, est également indisponible: il nécessite le type de résultat de la première Kleisli (B dans la signature) pour correspondre à l'entrée de type A de la seconde. Vous pouvez fournir des arguments et se déplacer vers le bas au niveau Task:

x(42) >> y("abc") 

Alternativement, si vous voulez rester au niveau Kleisli, vous pouvez utiliser la composition de flèche parallèle, comme indiqué dans d'autres réponses:

import scalaz.syntax.arrow._ // if you're not importing whole Scalaz 
import Function.const 
(x *** y).map(const()) // use map to ignore result 

Notez que cela signifie également que vous devrez fournir vos arguments plus tard.