Scala: why is a type used as a method call? - scala

Scala: why is a type used as a method call?
I'm new to Scala and I'm reading "Functional Programming in Scala"
by PAUL CHIUSANO and RÚNAR BJARNASON.
I'm trying to understand the source code of parser combinator in Chapter 9, but I'm stuck by a
problem: in the source code, Parser[A] is declared as a type, but I can see that instances of
Parser[A] is used as a method call.
My question is: why instance of a type can be used as a method
call?
def or[A](p: Parser[A], p2: => Parser[A]): Parser[A] =
s => p(s) match { // ========> p is used as a method call.
case Failure(e,false) => p2(s)
case r => r // committed failure or success skips running `p2`
}
Link to the source code:
https://github.com/fpinscala/fpinscala/blob/master/answers/src/main/scala/fpinscala/parsing
Code snippet:
trait Parsers[Parser[+_]] { self =>
.....
}
object ReferenceTypes {
/** A parser is a kind of state action that can fail. */
type Parser[+A] = ParseState => Result[A]
case class ParseState(loc: Location) {
......
}
sealed trait Result[+A] {
......
}
case class Success[+A](get: A, length: Int) extends Result[A]
case class Failure(get: ParseError, isCommitted: Boolean) extends Result[Nothing]
}
object Reference extends Parsers[Parser] {
......
def or[A](p: Parser[A], p2: => Parser[A]): Parser[A] =
s => p(s) match {
case Failure(e,false) => p2(s)
case r => r // committed failure or success skips running `p2`
}
.....
}

In the code you quoted, Parser[+A] is explicitly declared as function type
type Parser[+A] = ParseState => Result[A]
Therefore, values of type Parser[+A] can be applied to values of type ParseState. The usual syntax for applying a function p of type X => Y to a value s of type X is
p(s)
So, it's just usual function application, it's not even some fancy overriden apply method of some user-defined class.
A method call usually looks as follows:
obj.methodName(argument)
it requires an object on which the method is called. This can be omitted if the object is this, or if you have previously imported
import obj._
so that all methods of this object are available in the current scope. In all other cases, you need a receiving object on which you invoke a method.
The function application
p(s)
actually desugars into a special method call
p.apply(s)
but that's an aside, it's not really relevant for the question.

Related

How to chain generically chain functions returning Either with an operator like `andThen`?

Problem: Chaining multiple Either returning functions, the Left of which are all failures inheriting from a common sealed trait InternalError. However, the compiler complains that the chain is returning Either[_,Success] instead of Either[InternalError, Success].
Here's the code that does the chaining:
import scala.language.implicitConversions
object EitherExtension {
implicit class AndThenEither[A,B](val e: Function1[A,Either[_,B]]) {
//get ability to chain/compose functions that return aligning Eithers
def andThenE[C](f:Function1[B, Either[_,C]]): Function1[A, Either[_,C]] = {
(v1: A) => e.apply(v1).flatMap(b => f.apply(b))
}
}
}
As was pointed out in the comments this discards the type of Left. If I change it the below it will not work since the final output can be of type Either[X|Y, C] which resolves to Either[_,C] and I'm back to square one.
implicit class AndThenEither[A,B,X](val e: (A) => Either[X, B]) {
def andThenE[C,Y](f:(B) => Either[Y, C]): (A) => Either[_, C] = {
(v1: A) => e.apply(v1).flatMap(b => f.apply(b))
}
}
Here's the example showing the compositional failure of type alignment:
import EitherExtension._
object AndThenComposition {
//sample type definitions of failure responses
sealed trait InternalError
case class Failure1() extends InternalError
case class Failure2() extends InternalError
//sample type definitions
case class Id(id: Int)
case class Stuff()
//sample type definitions of successful responses
case class Output1()
case class Output2()
case class InputRequest()
val function1: (InputRequest) => Either[Failure1, Output1] = ???
val function2: (Output1) => Either[Failure2, Output2] = ???
def doSomething(s:Id, l:List[Stuff]): Either[InternalError, Output2] = {
val pipeline = function1 andThenE function2
pipeline(InputRequest()) //Why is this of type Either[_, Output2]
}
}
What am I missing? How can I get the return type to not be Either[Any, Output2] but rather the base/sealed trait? Is this possible to do generically?
You need to preserve the type of the left so we will modify the extension method to do that.
Note that, since both eithers can have different left types, what we will do is use a type bound to ask the compiler to infer the LUB between those types; thanks to Any this is always possibles (although not always helpful).
object EitherExtension {
implicit class AndThenEither[I, L1, R1](private val f: I => Either[L1, R1]) extends AnyVal {
def andThenE[L2 >: L1, R2](g: R1 => Either[L2, R2]): I => Either[L2, R2] =
i => f(i).flatMap(g)
}
}
Which can be used like this:
import EitherExtension._
object AndThenComposition {
sealed trait InternalError
final case object Failure1 extends InternalError
final case object Failure2 extends InternalError
val function1: Int => Either[Failure1.type, String] = ???
val function2: String => Either[Failure2.type, Boolean] = ???
def doSomething(input: Int): Either[InternalError, Boolean] = {
(function1 andThenE function2)(input)
}
}
See the code running here.
In case you're using this in production, and it's not just a learning thing, what you're looking for it's called Kleisli, and fortunately cats-core already implements it.
According to the cats-core docs:
Kleisli enables composition of functions that return a monadic value,
for instance an Option[Int] or a Either[String, List[Double]], without
having functions take an Option or Either as a parameter, which can be
strange and unwieldy.
Since Kleisli composes two functions with the signature A => F[B], you'd need only one abstraction to be able to use Kleisli, which is creating a new type for your operation:
type Operation[A] = Either[InternalFailure, A]
By doing this, you should be able to use Kleisli like this:
import cats.data.Kleisli
val first: Kleisli[Operation, InputRequest, Output1] = Kleisli { request: InputRequest =>
Left(Failure1())
}
val second: Kleisli[Operation, Output1, Output2] = Kleisli { output: Output1 =>
Right(Output2())
}
val composed = first.andThen(second)

Explain request passing in play framework

I was trying this in playframework. When I came through this part, at first it seemed pretty straightforward but while trying to trace it I'm not able to understand how this works. I know what kind of parameter is accepted by apply method of Action but I couldn't get how request is available and how it can be passed to Ok. Can anyone show analogous example with simple definition in scala.
#Singleton
class HomeController #Inject()(configuration: Configuration, cc: ControllerComponents)(implicit assetsFinder: AssetsFinder)
extends AbstractController(cc) {
def tweets = Action { implicit request =>
Ok(s"request is $request")
}
}
Thanks in advance
I'll try and simplify a bit:
trait A extends (String => String) { self => def apply() = this }
A effectively extends a function from String to String.
object A { def apply(f: String => String): A = new A { def apply(x: String) = f(x) } }
A's companion object actually implements A.
So you can now do this:
val f: String => String = _.toLowerCase
A(f)
This is valid Scala code.
You define f (toLowerCase on strings) and you pass it to the apply method of A.
This can also be written like this:
A { s => s.toLowerCase } // this way of putting it should remind you of Action { request => ... }
This is exactly how Play Action and EssentialAction works.
The other thing you ask is about Ok.
Ok is defined as a short version of Status with a set status code (200) and the given body (so something like Ok("Hello world!") will work.
On top of this there's the usual string interpolation you should know about.
Object Action extends trait DefaultActionBuilder extending trait ActionBuilder. The latter has method
apply(block: R[B] => Result): Action[B]
In your case request is of type Request[AnyContent] i.e. R is Request and B is AnyContent, Ok(s"request is $request") is of type Result,
Action { implicit request =>
Ok(s"request is $request")
}
is of type Action[B] i.e. Action[AnyContent]. So the syntax is just apply method of an object and a lambda as an argument of the method.
What is the apply function in Scala?
foo(implicit x => ???) is the same as foo(x => { implicit val x_ = x; ??? }).
Implicit keyword before a parameter in anonymous function in Scala
Ok is just new Status(OK) i.e. new Status(200) and class Status has method
def apply[C](content: C)(implicit writeable: Writeable[C]): Result
i.e. C is now String and content is s"request is $request" (i.e. string "request is " + request.toString).
If you use IDE you can investigate similar inheritance hierarchies and types yourself.

Scala function/method parametrized return type

I have just come up with something that I don't understand. I'm trying to return a parametrized type from a method, the code is the following (working example):
trait Expression
case class ExpImp1() extends Expression
case class ExpImp2() extends Expression
object Main {
private def testParametrizedTypes[T](): T = {
ExpImp1()
}
private def testWrappedParametrizedTypes[T <: Expression](): Option[T] = {
Some(new ExpImp1())
}
def main(args: Array[String]) {
}
}
but when I compile this code, the compiler says (the IDE warns me about the same error in both functions):
Error:(10, 12) type mismatch;
found : ExpImp1
required: T
ExpImp1()
^
I think that the code showed previously should work. In the first method I'm returning a type T and T has no constraint. The compiler error also occurs in the second method, but the parametrized type conforms to the returned object type too.
Also, I wrote a code a few weeks ago that looked like that that compiled with no problems (this is not a working example as this code is part of a Play Framework project):
class CanBeAuthenticatedRequest[A](val request: Request[A]) extends WrappedRequest[A](request)
class UnauthenticatedRequest[A](override val request: Request[A]) extends CanBeAuthenticatedRequest(request)
class AuthenticatedRequest[A](val user: String, override val request: Request[A]) extends CanBeAuthenticatedRequest[A](request)
object CanBeAuthenticatedAction extends ActionBuilder[CanBeAuthenticatedRequest] {
def invokeBlock[A]...
}
object Fold {
private def partialFunctionBuilder[T](authenticated: (AuthenticatedRequest[_]) => T)
(unauthenticated: (UnauthenticatedRequest[_]) => T):
PartialFunction[CanBeAuthenticatedRequest[_], T] = {
case ar: AuthenticatedRequest[_] => authenticated(ar)
case ur: UnauthenticatedRequest[_] => unauthenticated(ur)
}
def apply[T](request: CanBeAuthenticatedRequest[_])
(authenticated: (AuthenticatedRequest[_]) => T)
(unauthenticated: (UnauthenticatedRequest[_]) => T): T = {
partialFunctionBuilder(authenticated)(unauthenticated)(request)
}
}
}
As you can see, I successfully defined the function "partialFunctionBuilder" and I'm using it.
"partialFunctionBuilder" follows the same pattern, returning a type that is parametrized with "T". I don't see what's the difference between the code I showed first and the Play Framework code. Removing "<: Expression" from the "testWrappedParametrizedTypes" keeps giving me the same error.
When a function has a type parameter with some constraints, it should be possible to call it with any parameter, satisfying those constraints. So given the definitions it should be possible to call testParametrizedTypes[String]() or testWrappedParametrizedTypes[ExpImpl2](). But because in both cases you return a fixed type ExpImpl1, or Option[ExpImpl1], there is a type mismatch.
And in the Play example it is possible to call partialFunctionBuilder, with any type T, if you pass it the correct functions, which return that type T.

Limitations of implicit resolution or type inference

I'm trying to understand why implicit resolution (or perhaps type inference) fails for the following Scala code. In this code, compilation fails on the second to last line, but succeeds on a modified version of the line where types are explicitly provided.
object O {
trait Wrapper[-A, +B] {
def func: A => B
}
object Identity
implicit class Identity2Wrapper[A](self: Identity.type) extends Wrapper[A, A] {
override def func: A => A = identity
}
// Compilation fails on the next line with error:
// found String("hello")
// required: A
Identity.func("hello")
// This line compiles.
implicitly[Identity.type => Wrapper[String, String]].apply(Identity).func("hello")
}
Travis Brown seems to be right, this is an occurence of the following: https://issues.scala-lang.org/browse/SI-6472
As a proof, I could make it compile using the work around given by Travis himself here: https://issues.scala-lang.org/browse/SI-6776
object O {
trait Wrapper[-A, +B] {
val funcFunc: A => B
def func( arg: A ): B = funcFunc( arg )
}
private class Private
trait BaseWrappable {
// Dummy method (cannot ever be called, just a work around to help the compiler)
def func( a: Private ) = ???
}
object Identity extends BaseWrappable
implicit class Identity2Wrapper[A](self: Identity.type) extends Wrapper[A, A] {
val funcFunc: A => A = identity
}
Identity.func("hello")
}
The code you have written is the same as:
class Identity2Wrapper[A](self: Identity.type) extends Wrapper[A, A] {
override def func: A => A = identity
}
implicit def identityToIdentityWrapper[A](self: Identity.type) = new Identity2Wrapper[A](self)
Note that the type parameter A is unbound until the the result from the call to func is used. The Scala compiler is not smart enough to look that far ahead and determine the type of A. Also, you cannot create a value of type [A] A => A in Scala. I'm actually surprised that the compiler doesn't infer A to be of type Nothing like it does when you call identityToIdentityWrapper explicitly.

How is this a type mismatch?

val eventListeners = new HashMap[Class[Event], ArrayBuffer[Event => Unit]]
def addEventListener[A <: Event](f: A => Unit)(implicit mf: ClassManifest[A]): A => Unit = {
eventListeners.getOrElseUpdate(mf.erasure.asInstanceOf[Class[Event]], ArrayBuffer[Event => Unit]()) += f
f
}
Is throwing:
error: type mismatch;
found : (A) => Unit
required: (this.Event) => Unit
eventListeners.getOrElseUpdate(mf.erasure.asInstanceOf[Class[Event]], ArrayBuffer[Event => Unit]()) += f
Why is it saying that it found (A) => Unit? The value of f is a function that is (Event) => Unit. Isn't A just a type parameter, not the signature?
Example call:
addEventListener { e:FooEvent => .... }
The class Function1 is contra-variant on its parameter. Ie, its type is Function1[-T, +R].
That means a function of Any => Unit is a subtype of Event => Unit, but for A a subtype of Event, A => Unit is a _super_type of Event => Unit.
Ergo, the problem. If you change the type parameter to A >: Event, it should work.
You are promising your ArrayBuffer that you will give it a function that can take any Event and turn it into a Unit (presumably doing something interesting along the way).
But you are giving it a function that can only take As, which may not encompass all Events. That is clearly not what you've promised, so the compiler complains.
You need to figure out what ought to happen in that case, and write code accordingly. For example, you could create a new function g that does nothing in case it receives an Event that, according to your class manifest, is not an A, and otherwise applies f. Or you could require all listeners to take events of all sorts, and be responsible themselves for throwing away the events that they don't want to bother with.
Edit: just to make things clearer with an example,
abstract class Fruit { def tasty: String }
class Banana extends Fruit { def tasty = "Yum!" }
abstract class SeededFruit extends Fruit {
def seedCount: Int
def tasty = "Mmm, mmm."
}
class Peach extends SeededFruit { def seedCount = 1 }
class Apple extends SeededFruit { def seedCount = 5 }
val tellAboutSeeds = (sf: SeededFruit) => println("There are "+sf.seedCount+"seeds")
val fruitTeller = new collection.mutable.ArrayBuffer[Fruit=>Unit]
fruitTeller += tellAboutSeeds // If this worked...
fruitTeller(0)(new Banana) // ...we'd be in trouble!