Cartesian product traverse in scalaz

前端 未结 4 820
逝去的感伤
逝去的感伤 2021-02-10 03:06

In Eric Torreborre\'s blogpost on the paper Essence of the Iterator Pattern, he describes how the cartesian product of a traverse is also a traverse.

Can anyone show me

4条回答
  •  梦毁少年i
    2021-02-10 03:42

    Debasish Ghosh has written a nice post on this topic. Based on the code in that post:

    scala> List(1, 2, 3, 4)
    res87: List[Int] = List(1, 2, 3, 4)
    
    scala> .traverse[({ type L[X] = State[Int, X] })#L, String] { cur =>
         |   state { (acc: Int) => (acc + cur, cur.toString + "Z") }
         | }
    res88: scalaz.State[Int,List[String]] = scalaz.States$$anon$1@199245
    
    scala> .apply(0)
    res89: (Int, List[String]) = (10,List(1Z, 2Z, 3Z, 4Z))
    

    Edit:

    You have two functions List[A] => B and List[A] => C, and you want a function List[A] => (B, C). That's what &&& is for. This won't fuse the loops though. I cannot imagine how it can be possible to fuse loops for such a case.

    Fwiw, code:

    scala> val shape = (_ : List[Int]) map (_.toString + "Z")
           val accum = (_ : List[Int]).sum
    shape: List[Int] => List[java.lang.String] = 
    accum: List[Int] => Int = 
    
    scala> val xs = List(1, 2, 3, 4)
    xs: List[Int] = List(1, 2, 3, 4)
    
    scala> (shape &&& accum) apply xs
    res91: (List[java.lang.String], Int) = (List(1Z, 2Z, 3Z, 4Z),10)
    

    Edit 2:

    If you have functions A => B and A => C you can merge them into A => (B, C) using &&&. Now if B : Monoid and C : Monoid, you can use foldMap to get List[A] => (B, C). This will do the stuff in one loop.

    Code:

    scala> val f: Int => Int = identity
    f: Int => Int = 
    
    scala> val g: Int => List[String] = i => List(i.toString + "Z")
    g: Int => List[String] = 
    
    scala> List(1, 2, 3, 4).foldMap(f &&& g)
    res95: (Int, List[String]) = (10,List(1Z, 2Z, 3Z, 4Z))
    

    Final edit: (I swear I am not editing this again.)

    Since these concepts have their origins in Haskell, I thought it'd be a good idea to re-post this question under Haskell tag, and I did. The answer there seems to be consistent with whatever I have said in this thread. Hôpe this helps.

提交回复
热议问题