score:81
To quote myself:
So why bother with applicative functors at all, when we've got monads? First of all, it's simply not possible to provide monad instances for some of the abstractions we want to work with—
Validation
is the perfect example.Second (and relatedly), it's just a solid development practice to use the least powerful abstraction that will get the job done. In principle this may allow optimizations that wouldn't otherwise be possible, but more importantly it makes the code we write more reusable.
To expand a bit on the first paragraph: sometimes you don't have a choice between monadic and applicative code. See the rest of that answer for a discussion of why you might want to use Scalaz's Validation
(which doesn't and can't have a monad instance) to model
validation.
About the optimization point: it'll probably be a while before this is generally relevant in Scala or Scalaz, but see for example the documentation for Haskell's Data.Binary
:
The applicative style can sometimes result in faster code, as
binary
will try to optimize the code by grouping the reads together.
Writing applicative code allows you to avoid making unnecessary claims about dependencies between computations—claims that similar monadic code would commit you to. A sufficiently smart library or compiler could in principle take advantage of this fact.
To make this idea a little more concrete, consider the following monadic code:
case class Foo(s: Symbol, n: Int)
val maybeFoo = for {
s <- maybeComputeS(whatever)
n <- maybeComputeN(whatever)
} yield Foo(s, n)
The for
-comprehension desugars to something more or less like the following:
val maybeFoo = maybeComputeS(whatever).flatMap(
s => maybeComputeN(whatever).map(n => Foo(s, n))
)
We know that maybeComputeN(whatever)
doesn't depend on s
(assuming these are well-behaved methods that aren't changing some mutable state behind the scenes), but the compiler doesn't—from its perspective it needs to know s
before it can start computing n
.
The applicative version (using Scalaz) looks like this:
val maybeFoo = (maybeComputeS(whatever) |@| maybeComputeN(whatever))(Foo(_, _))
Here we're explicitly stating that there's no dependency between the two computations.
(And yes, this |@|
syntax is pretty horrible—see this blog post for some discussion and alternatives.)
The last point is really the most important, though. Picking the least powerful tool that will solve your problem is a tremendously powerful principle. Sometimes you really do need monadic composition—in your getPhoneByUserId
method, for example—but often you don't.
It's a shame that both Haskell and Scala currently make working with monads so much more convenient (syntactically, etc.) than working with applicative functors, but this is mostly a matter of historical accident, and developments like idiom brackets are a step in the right direction.
score:28
Functor is for lifting computations to a category.
trait Functor[C[_]] {
def map[A, B](f : A => B): C[A] => C[B]
}
And it works perfectly for a function of one variable.
val f = (x : Int) => x + 1
But for a function of 2 and more, after lifting to a category, we have the following signature:
val g = (x: Int) => (y: Int) => x + y
Option(5) map g // Option[Int => Int]
And it is the signature of a applicative functor. And to apply the following value to a function g
— an aplicative functor is needed.
trait Applicative[F[_]] {
def apply[A, B](f: F[A => B]): F[A] => F[B]
}
And finally:
(Applicative[Option] apply (Functor[Option] map g)(Option(5)))(Option(10))
Applicative functor is a functor for applying a special value (value in category) to a lifted function.
Source: stackoverflow.com
Related Query
- When and why should one use Applicative Functors in Scala
- Why and how is Scala treating a tuple specially when calling a one arg function?
- Why was Manifest deprecated? When should I use ClassTag and when should I use TypeTag
- Why is Scala unable to infer the type of an anonymous function when there is method overloading and only one method takes a function?
- When should I use a Scala class and when to use Scala object in IDE?
- How do you use map-reduce in scala dataframes when u have 2 fields and second field should be split?
- What is the formal difference in Scala between braces and parentheses, and when should they be used?
- What's the standard way to work with dates and times in Scala? Should I use Java types or there are native Scala alternatives?
- What are Scala continuations and why use them?
- When should one use a Kleisli?
- What does the @elidable annotation do in Scala, and when should I use it?
- Why should one use a http server in front of a framework web server?
- One Play 2 Framework App - use both java and scala
- When should I use Option.empty[A] and when should I use None in Scala?
- why use def and val in Scala or vice versa
- what is the difference between HashSet and Set and when should each one be used?
- When should I use package and when object in Scala?
- Scala - how to explicitly choose which overloaded method to use when one arg must be null?
- When should I use Scala's Array instead of one of the other collections?
- When to use scala triple caret (^^^) vs double caret (^^) and the into method (>>)
- When does it make sense to use implicit parameters in Scala, and what may be alternative scala idioms to consider?
- Why should I use object vs trait Dependencies and import it vs mixin to build definition?
- When one should call resetProxy and clearSelf methods of Actor?
- Scala Play Websocket - use one out actor to send both: Array[Byte] and String messages
- When and Why do you use State Monads?
- When should one use applicatives over monads?
- Why does scala compiler fail to find implicit parameter value/conversion when it is an overload and has generic type param?
- When should a Scala method def use an explicitly defined return type?
- Idea 13 and Gradle when trying to use scala-compiler in the Scala facets does not find scala-library
- Why and when should trait and object have same name?
More Query from same tag
- (), (Nothing) and _ in Scala
- Transform rows to columns in Spark Scala SQL
- Task serialization error when using UDF in Spark
- Generate sql query by anorm, with all nulls except one
- How can I implement a monadic interface (map, flatMap) for a type R[Out] { type In }?
- A simple Scala Given/When/Then style specification failed
- Logging the time for each test (and/or testSuite) with scala test
- LUB for Function2 and Function3 trait
- Spark SQL average non zero values
- How to export Spark GraphX graph to Gephi using scala
- @tailrec why does this method not compile with 'contains a recursive call not in tail position'?
- How to remove scala version from an sbt multi project with cross build on a particular project
- Deal with foreign keys
- Automatically create StructType from avsc file
- How to write process files and write the results in parallel in Scala?
- Expected type and polymorphic function with implicit parameters confuses type inference?
- Error while running Scala code - Databricks 7.3LTS and above
- How to concisely check if tuples have no overlappping members
- Scala subString function
- scala how to use pattern matching with inheriance and templated class
- create dataframe in scala with List of strings
- Slick MTable.getTables always fails with Unexpected exception[JdbcSQLException: Invalid value 7 for parameter columnIndex [90008-60]]
- Issue with try-finally in Scala
- Partially applied type lambda in Scala with kind projector
- How to split lines in a file into groups?
- Find objects in one site but not another without using the set operation diff
- Is it possible to have tuple assignment to variables in Scala?
- Can anyone explain me this code in scala ?
- Scala functional code for iteration with a value forwarded to next iteration
- Deleting records in a table with billion records using spark or scala