thlim
thlim

Reputation: 2982

How to Remove Explicit Casting

How do I remove explicit casting asInstanceOf[XList[B]] in Cons(f(a), b).asInstanceOf[XList[B]] inside map function? Or perhaps redesign reduce and map functions altogether? Thanks

trait XList[+A]
case object Empty extends XList[Nothing]
case class Cons[A](x: A, xs: XList[A]) extends XList[A]

object XList {
  def apply[A](as: A*):XList[A] = if (as.isEmpty) Empty else Cons(as.head, apply(as.tail: _*))
  def empty[A]: XList[A] = Empty
}

def reduce[A, B](f: B => A => B)(b: B)(xs: XList[A]): B = xs match {
  case Empty => b
  case Cons(y, ys) => reduce(f)(f(b)(y))(ys)
}

def map[A, B](f: A => B)(xs: XList[A]): XList[B] = reduce((b: XList[B]) => (a: A) => Cons(f(a), b).asInstanceOf[XList[B]])(XList.empty[B])(xs)

Upvotes: 1

Views: 69

Answers (2)

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149626

You can either widen Cons to a XList[B] at the call site by providing the type parameters explicitly:

def map[A, B](f: A => B)(xs: XList[A]): XList[B] =
  reduce[A, XList[B]]((b: XList[B]) => (a: A) => Cons(f(a), b))(XList.empty[B])(xs)

Or use type ascription:

def map[A, B](f: A => B)(xs: XList[A]): XList[B] =
  reduce((b: XList[B]) => (a: A) => Cons(f(a), b): XList[B])(XList.empty[B])(xs)

As a side note, reduce is traditionally more strict at the method definition than what you've written. reduce usually looks like this:

def reduce[A](a0: A, a: A): A

Implicitly requiring a non empty collection to begin with. What you've implemented is similar in structure to a foldLeft, which has this structure (from Scalas collection library):

def foldLeft[B](z: B)(op: (B, A) => B): B

Upvotes: 0

Andrey Tyukin
Andrey Tyukin

Reputation: 44977

You can merge two argument lists into one by replacing )( by ,:

def reduce[A, B](f: B => A => B, b: B)(xs: XList[A]): B = xs match {
  case Empty => b
  case Cons(y, ys) => reduce(f, f(b)(y))(ys)
}

def map[A, B](f: A => B)(xs: XList[A]): XList[B] = 
  reduce((b: XList[B]) => (a: A) => Cons(f(a), b), XList.empty[B])(xs)

This will force the type inference algorithm to consider both first arguments of reduce before making up its mind about what B is supposed to be.

Upvotes: 1

Related Questions