bbarker
bbarker

Reputation: 13108

How to map over function's input in Scala?

I am trying to create a map that can convert the input type of a function to another type. Normally when we map, we have a function A => B, but since we are mapping the inputs in functions, I believe this means we actually need a function B => A, as in the following:

  enum Result[+V, +E, +A]:
    case View(view: V)
    case Eff(eff: IO[E, Unit])
    case Res(result: A, remaining: Unit => Any)
  object Result {
    def map[A,B,V,E](fn: A => B)(res: Result[V,E,A]): Result[V,E,B] = res match {
      case View(v) => View(v)
      case Eff(e) => Eff(e)
      case Res(res, rem) => Res(fn(res), rem)
    }
  }
  type ResultRun[V,E,A] = Result[V, E, A] => IO[E, Unit]
  object ResultRun {
    // f: A -> C
    // fn: B -> A
    // fn andThen f : B -> C
    def map[V,E,A,B](fn: B => A)(rr: ResultRun[V,E,A]): ResultRun[V,E,B] = Result.map(fn).andThen(rr)
  }

This results in the following type error, which likely indicates I'm doing something wrong that is more fundamental than indicated by the error:

[error] 50 |    def map[V,E,A,B](fn: B => A)(rr: ResultRun[V,E,A]): ResultRun[V,E,B] = Result.map(fn).andThen(rr)
[error]    |                                                                                                  ^^
[error]    |Found:    (rr : concur.Types.ResultRun[V, E, A])
[error]    |Required: concur.Types.Result[Any, Any, A] => IO[E, Unit]
[error]    |
[error]    |One of the following imports might make progress towards fixing the problem:
[error]    |
[error]    |  import scalajs.js.Any.fromFunction1
[error]    |  import scalajs.js.ThisFunction.fromFunction1

Also, maybe this should be called contraMap, instead of map.

Upvotes: 1

Views: 113

Answers (1)

esse
esse

Reputation: 1551

Where is the IO in case Eff(eff: IO[E, Unit]) come from ?

The following code compiles if I defined IO as case class IO[+X, -Y]():

  enum Result[+V, +E, +A]:
    case View(view: V)
    case Eff(eff: IO[E, Unit])
    case Res(result: A, remaining: Unit => Any)
  object Result {
    def map[A,B,V,E](fn: A => B)(res: Result[V,E,A]): Result[V,E,B] = res match {
      case View(v) => View(v)
      case Eff(e) => Eff(e)
      case Res(res, rem) => Res(fn(res), rem)
    }
  }
  type ResultRun[V,E,A] = Result[V, E, A] => IO[E, Unit]
  object ResultRun {
    // f: A -> C
    // fn: B -> A
    // fn andThen f : B -> C
    def map[V,E,A,B](fn: B => A)(rr: ResultRun[V,E,A]): ResultRun[V,E,B] = Result.map[B, A, V, E](fn).andThen(rr)
  }

Upvotes: 1

Related Questions