user2051561 - 4 months ago 26

Scala Question

I have a type inference issue and asked for help here.

The initial problem was due to overload. Once corrected I

still had problems.

So here is the code:

`class DPipe[ A ]( a: A ) {`

def !>[ B ]( f: A => B ) = Try(f( a ))

def #>[ B, C ]( f: B => C )(implicit ev: A =:= Try[B]) : Try[C] = a.map(f)

//def &>[ B, C ]( f: B => C )( implicit ev: A =:= Try[ B ] ) = a.map( f )

}

object DPipe {

def apply[ A ]( v: A ) = new DPipe( v )

}

object DPipeOps {

implicit def toDPipe[ A ]( a: A ): DPipe[ A ] = DPipe( a )

}

And here are the tests:

`object DPipeDebug {`

def main( args: Array[ String ] ) {

import DPipeOps._

val r8 = 100.0 !> {x : Double => x / 0.0}

println(r8)

val r9 = r8 #> {x:Double => x* 3.0}

println(r9)

/*

val r8 = 100.0 !> { x: Double => x / 0.0 }

println( r8.get )

val r9 = r8 &> { x: Double => x * 3.0 }

println( r9 )*/

val r10 = (100.0 !> {x : Double => x / 0.0}) #> {x:Double => x* 3.0}

//val r10 = ( 100.0 !> { x: Double => x / 0.0 } ) &> { x: Double => x * 3.0 }

val r11 = 100.0 !> {x : Double => x / 0.0} #> {x:Double => x* 3.0}

//val r11 = 100.0 !> { x: Double => x / 0.0 } &> { x: Double => x * 3.0 }

}

}

As it stands we have the following error in the last code line:

`Cannot prove that Double => Double =:= scala.util.Try[Double].`

val r11 = 100.0 !> {x : Double => x / 0.0} #> {x:Double => x* 3.0}

^

Notice that in the second last code line, I need only add

the parenthesis to enforce left left-hand associativity

(Scala default). It seems like the

`#>`

use the function

`{x : Double => x / 0.0}`

Double.

If however I use the "&>" operator, no error occurs. In the

test code below, just flip the comments. So my question is, why

is this happening. Is this something new to Scala 2.12.0?

TIA

Answer

The problem is with the operator precedence. Here are more details: Operator precedence in Scala

It depends on the first character of the operator. `#`

has higher precedence than `!`

and `!`

has higher precedence than `&`

.

Hence you get

```
100.0 !> ({x : Double => x / 0.0} #> {x:Double => x* 3.0})
```

instead of

```
(100.0 !> {x : Double => x / 0.0}) #> {x:Double => x* 3.0}
```