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.
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)
}
Related
How to provide a type disjunction for 3 or more types in shapeless? Example:
import shapeless._
object Tst extends App {
sealed trait Base
final case class A() extends Base
final case class B() extends Base
final case class C() extends Base
final case class D() extends Base
def AorB[T: (A |∨| B)#λ](t: T): Unit =
t match {
case _: A => println("A")
case _: B => println("B")
}
AorB(A()) //Ok
AorB(B()) //Ok
def AorBorC[T: (A |∨| B |∨| C)#λ](t: T): Unit =
t match {
case _: A => println("A")
case _: B => println("B")
case _: C => println("C")
}
AorBorC(A()) //compile-error
AorBorC(B()) //compile-error
AorBorC(C()) //Ok
}
As can be seen for disjunction of 2 types it works completely fine. But for disjunction of 3 types it does not work as expected.
Compile errors are:
Error:(28, 10) Cannot prove that (Tst.A => Nothing) => Nothing <:< Object{type λ[X] = (X => Nothing) => Nothing <:< Tst.A => Nothing with Tst.B => Nothing => Nothing} => Nothing with Tst.C => Nothing => Nothing.
AorBorC(A())
and
Error:(29, 10) Cannot prove that (Tst.B => Nothing) => Nothing <:< Object{type λ[X] = (X => Nothing) => Nothing <:< Tst.A => Nothing with Tst.B => Nothing => Nothing} => Nothing with Tst.C => Nothing => Nothing.
AorBorC(B())
shapeless.|∨| doesn't work for more than 2 types.
http://milessabin.com/blog/2011/06/09/scala-union-types-curry-howard/
For more than 2 types encoding becomes more complicated.
One encoding is for 2, 4, 8 ... types
type ¬¬¬¬[T] = ¬¬[¬¬[T]]
type |∨∨|[T, U] = {
type λ[X] = ¬¬¬¬[X] <:< (T ∨ U)
}
def AorBorC[T: ((A ∨ B) |∨∨| (C ∨ C))#λ](t: T): Unit =
t match {
case _: A => println("A")
case _: B => println("B")
case _: C => println("C")
}
AorBorC(A()) //Ok
AorBorC(B()) //Ok
AorBorC(C()) //Ok
Another is for arbitrary number of types
trait Disj[T] {
type or[S] = Disj[T with ¬[S]]
type apply = ¬[T]
}
type ∨∨∨[T1, T2, T3] = Disj[¬[T1]]#or[T2]#or[T3]#apply
type |∨∨∨|[T1, T2, T3] = {
type λ[X] = ¬¬[X] <:< ∨∨∨[T1, T2, T3]
}
def AorBorC[T: |∨∨∨|[A, B, C]#λ](t: T): Unit =
t match {
case _: A => println("A")
case _: B => println("B")
case _: C => println("C")
}
AorBorC(A()) //Ok
AorBorC(B()) //Ok
AorBorC(C()) //Ok
How to define "type disjunction" (union types)?
Working through the excellent "FP in Scala" by Chiusano Rúnar Bjarnason, had a strange compilation error when trying to implement Stream#takeWhile lazily through #foldRight. Given the following code in the book (also on GitHub):
trait Stream[+A] {
def foldRight[B](z: => B)(f: (A, => B) => B): B =
this match {
case Cons(h,t) => f(h(), t().foldRight(z)(f))
case _ => z
}
case object Empty extends Stream[Nothing]
case class Cons[+A](h: () => A, t: () => Stream[A]) extends Stream[A]
object Stream {
def cons[A](hd: => A, tl: => Stream[A]): Stream[A] = {
lazy val head = hd
lazy val tail = tl
Cons(() => head, () => tail)
def empty[A]: Stream[A] = Empty
}
I tried:
def takeWhile_fold(p: A => Boolean): Stream[A] =
foldRight(empty[A])((it:A, acc:Stream[A]) => if (p(it)) cons(it, acc) else acc)
But this gives the compilation fault:
type mismatch;
[error] found : (A, fpinscala.laziness.Stream[A]) => fpinscala.laziness.Stream[A]
[error] required: (A, => fpinscala.laziness.Stream[A]) => fpinscala.laziness.Stream[A]
[error] foldRight(empty[A])((it:A, acc:Stream[A]) => if (p(it)) cons(it, acc) else ac
But if I remove the types on the lambda, it works:
def takeWhile_fold(p: A => Boolean): Stream[A] =
foldRight(empty[A])((it, acc) => if (p(it)) cons(it, acc) else acc)
There is no way in Scala to state in the calling code that it should be a by-name parameter, is there? (Does it even make sense for the caller, it is the receiver that decides, right?) Attempting:
def takeWhile_fold(p: A => Boolean): Stream[A] =
foldRight(empty[A])((it, acc: => Stream[A]) => if (p(it)) cons(it, acc) else acc)
Gives another compilation error:
[error] identifier expected but '=>' found.
[error] foldRight(empty[A])((it, acc: => Stream[A]) => if (p(it)) cons(it, acc) else acc)
^
[error] ')' expected but '}' found.
[error] }
[error] ^
[error] two errors found
I've solved the exercise, but my questions are - why doesn't it work with explicit types? Do they enforce strictness somehow while the receiver must have non-strict? And if so, is there any syntax in Scala so the caller can signal that "yes, this is by-name parameters"?
Yes, by-name ends up being part of the signature. You can imagine that by-name parameters are implemented by the compiler by translating this:
def foo(n: => Int) = ... n ...
to this:
def foo(n: () => Int) = ... n() ...
A side effect of this is that, if you reference by-name parameters multiple times, they will be evaluated multiple times. So this:
def bar(n: => Int) = n + n
bar( { println("foo"); 5 } )
Will print foo twice before returning 10. It's the same as this:
def bar(n: () => Int) = n() + n()
bar { () => println("foo"); 5 }
As for whether you can explicitly state that a lambda takes by-name parameters... I'm not sure. I tried this:
def foo( f: ( => Int) => Int ) = f({ println("foo"); 5 })
foo { (a) => a + a }
Which worked. I tried these:
foo { (a : Int ) => a + a }
foo { (a : => Int ) => a + a }
Which failed.
The spec seems to indicate that the type property of formal parameters to functions are generated with the ParamType syntax rule, whereas the type property of anonymous functions parameters uses the plain Type rule. And the => by-name indicator is on ParamType.
I'm working on map3 from Functional Programming in Scala:
// Exercise 3: The apply method is useful for implementing map3, map4, and so on
// and the pattern is straightforward. Implement map3 and map4 using only
// unit, apply, and the curried available on functions.
def map3[A,B,C,D](fa: F[A],
fb: F[B],
fc: F[C])(f: (A, B, C) => D): F[D] = {
def foo: (A => B => C => D) = (f _).curried // compile-time error
def fooF: F[A => B => C => D] = unit(foo)
val x: F[B => C => D] = apply(fooF)(fa)
val y: F[C => D] = apply(x)(fb)
val z: F[D] = apply(y)(fc)
z
}
One(1) compile-time error occurs on the above, noted line:
[error] C:\...\Applicative.scala: _ must follow method; cannot follow f.type
[error] def foo: (A => B => C => D) = (f _).curried
[error]
^
I was able to successfully get the curried version of a function via this post - Using FunctionX#curried.
However, I don't understand the above compile-time error.
The error is because f here is a function, not a method; the f _ syntax is to turn methods into functions, which isn't necessary here. Simply write def foo: A => B => C => D = f.curried.
Using some structure:
object Foo {
trait Bar[B]
}
trait Foo[A, B, F <: Foo[A, B, F]] {
def baz(fun: A => Foo.Bar[B] => Unit): Unit
}
...why are existential types causing trouble:
def test[A, F <: Foo[A, _, F]](foo: F) =
foo.baz { a => b => println(b) }
The following error occurs:
<console>:38: error: type mismatch;
found : A => Foo.Bar[(some other)_$1(in type F)] => Unit
forSome { type (some other)_$1(in type F) }
required: A => (Foo.Bar[_$1(in type F)] => Unit)
foo.baz { a => b => println(b) }
^
While the following compiles:
def test[A, JamesClapperSociopath, F <: Foo[A, JamesClapperSociopath, F]](foo: F) =
foo.baz { a => b => println(b) }
It must have something to do with equivalence of existential types. The compiler probably infers b: F#_$1 and then can't figure out that the two projections are equal.
Fortunately, functions are contravariant in the parameter type, so you can just write:
def test[A, F <: Foo[A, _, F]](foo: F) =
foo.baz { a => (b: Any) => println(b) }
Does the Scala library provide any support for lifting a method of a given type to a function value?
For example, suppose I want to lift String.length. I can write
val f: String => Int = _.length
or
val f = { s: String => s.length }
However, this syntax is not always ideal (particularly in the midst of a larger expression). I think I'm looking for something that will enable expressions like
Lift[String](_.length)
Lift[Option[Int]].lift(_.filter)
and I have in mind something like this:
class Lift[T] {
def apply[R](f: T => R): T => R = f
def lift[A, R](f: (T) => (A) => R): (T, A) => R =
f(_)(_)
def lift[A1, A2, R](f: (T) => (A1, A2) => R): (T, A1, A2) => R =
f(_)(_,_)
// ... etc. ...
}
object Lift {
def apply[T] = new Lift[T]
}
Question 1: Does the standard library (or any library) provide something like this?
Question 2: If not, is it possible to write it in such a way that Option.filter can be lifted as above (rather than as Lift[Option[Int]].lift[Int => Boolean, Option[Int]](_.filter))? Without supplying the type parameters on the lift method I get the following error:
error: missing parameter type for expanded function ((x$1) => x$1.filter)
Lift[Option[Int]].lift(_.filter)
^
Update:
Apparently, the problem I'm running in to has something to do with the overloaded lift method. If I rename the overloads, I can lift Option.filter without all the extra type parameters.
What is the problem with
(_: String).length
(_: Option[Int]).filter _
?
I finally came up with a solution that I'm happy with. This version supports simple syntax and a single entry point to the API, while also providing control over the form of the lifted function (i.e. uncurried, partly curried, or fully curried).
Examples:
I'll use the following class definition in the examples below:
class Foo {
def m1: Int = 1
def m2(i: Int): Int = i
def m3(i: Int, j: Int): Int = i + j
}
The simplest form of lifting is to return the method as a partially applied function, equivalent to invoking ((_: Foo).method _):
scala> lift[Foo](_.m1) // NOTE: trailing _ not required
res0: (Foo) => Int = <function1>
scala> lift[Foo](_.m2 _) // NOTE: trailing _ required
res1: (Foo) => (Int) => Int = <function1>
scala> lift[Foo](_.m3 _)
res2: (Foo) => (Int, Int) => Int = <function1> // NOTE: the result is partly curried
By importing some implicits, one can request curried or uncurried forms:
scala> {
| import CurriedLiftables._
| lift[Foo](_.m3 _)
| }
res3: (Foo) => (Int) => (Int) => Int = <function1>
scala> {
| import UncurriedLiftables._
| lift[Foo](_.m3 _)
| }
res4: (Foo, Int, Int) => Int = <function3>
Implementation:
class Lift[T] {
def apply[R,F](f: T => R)(implicit e: (T => R) Liftable F): F = e.lift(f)
}
object lift {
def apply[T] = new Lift[T]
}
class Liftable[From, To](val lift: From => To)
class DefaultLiftables {
implicit def lift[F]: F Liftable F = new Liftable(identity)
}
object Liftable extends DefaultLiftables
class UncurriedLiftable1 extends DefaultLiftables {
implicit def lift1[T, A, R]: (T => A => R) Liftable ((T, A) => R) =
new Liftable( f => f(_)(_) )
}
class UncurriedLiftable2 extends UncurriedLiftable1 {
implicit def lift2[T, A1, A2, R]: (T => (A1, A2) => R) Liftable ((T, A1, A2) => R) =
new Liftable ( f => f(_)(_,_) )
}
// UncurriedLiftable3, UncurriedLiftable4, ...
object UncurriedLiftables extends UncurriedLiftable2
class CurriedLiftable2 extends DefaultLiftables {
implicit def lift2[T, A1, A2, R]: (T => (A1, A2) => R) Liftable (T => A1 => A2 => R) =
new Liftable( f => (x: T) => (a1: A1) => (a2: A2) => f(x)(a1, a2) )
}
// CurriedLiftable3, CurriedLiftable4, ...
object CurriedLiftables extends CurriedLiftable2
My previous solution required a separate lift method for each arity:
import Lift._
val f1 = lift0[String](_.length)
val f2 = lift1[Option[Int]](_.filter)
val f3 = lift2[Either[String, Int]](_.fold)
Implementation:
class Lift0[T] {
def apply[R](f: T => R): T => R = f
}
class Lift1[T] {
def apply[A, R](f: (T) => (A) => R): (T, A) => R =
f(_)(_)
}
class Lift2[T] {
def apply[A1, A2, R](f: (T) => (A1, A2) => R): (T, A1, A2) => R =
f(_)(_,_)
}
// ... etc. ...
object Lift {
def lift0[T] = new Lift0[T]
def lift1[T] = new Lift1[T]
def lift2[T] = new Lift2[T]
// ... etc. ...
}
Passing in filter as partially applied method seems to do the job:
scala> class Lift[T] {
| def apply[R](f: T => R): T => R = f
| }
defined class Lift
scala> object Lift {
| def apply[T] = new Lift[T]
| }
defined module Lift
scala> val ls = Lift[String](_.length)
ls: (String) => Int = <function1>
scala> val los = Lift[Option[Int]](_.filter _)
los: (Option[Int]) => ((Int) => Boolean) => Option[Int] = <function1>