1

I've created a type

type ResultLog = Writer[List[String], Option[Double]]

My function called process wants to works on a list of Inputs and return ResultLog :

def process(inputs : List[Input]): ResultLog = {

    for {
      input <- inputs
      res <- if(input.date == "28092018"){
        Writer(List(s"Wrong date ${input.date} of ${input.id} "), None)
      } else {
       Writer(Nil, Some(input.value))
      }
    } yield res
  }

Input is a case class:

case class Input(date:String, id: Int, value : Double)

What I'm getting is these compiler error:

Error:(14, 11) type mismatch;
 found   : _2(in value $anonfun) => _2(in value $anonfun) where type _2(in value $anonfun) >: None.type with Some[Double] <: Option[Double]
 required: (some other)_2(in value $anonfun) => ? where type (some other)_2(in value $anonfun) >: None.type with Some[Double] <: Option[Double]
      res <- if(input.date == "28092018"){
Error:(14, 11) type mismatch;
 found   : _2(in value $anonfun) => _2(in value $anonfun) where type _2(in value $anonfun) >: None.type with Some[Double] <: Option[Double]
 required: _2(in value $anonfun) => ? where type _2(in value $anonfun) >: None.type with Some[Double] <: Option[Double]
      res <- if(input.date == "28092018"){
Error:(13, 13) type mismatch;
 found   : List[Nothing]
 required: Aggregation.this.ResultLog
    (which expands to)  cats.data.WriterT[cats.Id,List[String],Option[Double]]
      input <- inputs

What I am doing wrong?

Update:

After reading the comments, I changed my function to combine the double values rather than just passing as it is. This compiles fine :

type ResultLog[A] = Writer[Vector[String], A]

def process2(inputs  :List[Input]): ResultLog[Option[Double]] = {
import cats.syntax.applicative._
import cats.instances.vector._

inputs.foldLeft(Writer(Vector(""),Option(0.0))){
  (z , i) => {
    if(i.cobDate == "28092018") {
      Writer(Vector(s"Wrong cobdate ${i.cobDate} of reportingSetId: ${i.reportingSetId}"), None)
    } else {
      z.value.flatMap(zv => Some(zv + i.value)).pure[ResultLog]
    }
  }
}

}

Imran K
  • 81
  • 1
  • 12
  • It's not clear what `process` should do. For each input you have either message for log or double value. Maybe you'd like to concatenate logs. But what would you like to do with all double values? – Dmytro Mitin May 08 '19 at 22:48
  • There's not much meaning in what `process` does, I'm just trying to understand how to use cats.Writer in cases where I've a list of inputs, and some of them might fail for which I'll log a message, and for rest of the inputs, I might combine the double values. – Imran K May 09 '19 at 05:50
  • 2
    Possible duplicate of [Using different monads in for-comprehension](https://stackoverflow.com/questions/33401077/using-different-monads-in-for-comprehension) – Dmytro Mitin May 09 '19 at 08:02

1 Answers1

0

You cannot use <- operator for different data types inside a for comprehension. Try using = instead.

for {
      input <- inputs
      res = if(input.date == "28092018"){ // Use = instead of <-
        Writer(List(s"Wrong date ${input.date} of ${input.id} "), None)
      } else {
       Writer(Nil, Some(input.value))
      }
    } yield res
Dionysis Nt.
  • 955
  • 1
  • 6
  • 16
  • Then returning type of `process` is not `ResultLog`. – Dmytro Mitin May 08 '19 at 22:49
  • of course. The for comprehension is equivalent to doing `inputs.map(input=> doStuff)`. So this block of code returns one `ResultLog` for **each** element of the list. It will compile if you change the return type to `List[ResultLog]` but not sure what you want to do exactly – Dionysis Nt. May 09 '19 at 07:39
  • Ok, as I told before, I'm trying to find a way to return the type ResultLog from `process`. Lets say I'll add all the `input.value` if the date is not a particular date (say, 28092018), in that case there will be no message. But among the inputs if one them has date 28092018, then I'll stop adding the doubles at that point, and return that value with the message : `wrong date 28092018 of $id` – Imran K May 09 '19 at 16:10