Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <h3>Type Constructors as Type Parameters</h3> <p><code>M</code> is a type parameter to one of Scalaz's main pimps, <a href="http://scalaz.googlecode.com/svn/continuous/latest/browse.sxr/scalaz/MA.scala.html" rel="noreferrer">MA</a>, that represents the Type Constructor (aka Higher Kinded Type) of the pimped value. This type constructor is used to look up the appropriate instances of <code>Functor</code> and <code>Apply</code>, which are implicit requirements to the method <code>&lt;**&gt;</code>.</p> <pre><code>trait MA[M[_], A] { val value: M[A] def &lt;**&gt;[B, C](b: M[B], z: (A, B) =&gt; C)(implicit t: Functor[M], a: Apply[M]): M[C] = ... } </code></pre> <h3>What is a Type Constructor?</h3> <p>From the Scala Language Reference:</p> <blockquote> <p>We distinguish between first-order types and type constructors, which take type parameters and yield types. A subset of first-order types called value types represents sets of (first-class) values. Value types are either concrete or abstract. Every concrete value type can be represented as a class type, i.e. a type designator (§3.2.3) that refers to a class1 (§5.3), or as a compound type (§3.2.7) representing an intersection of types, possibly with a refinement (§3.2.7) that further constrains the types of itsmembers. Abstract value types are introduced by type parameters (§4.4) and abstract type bindings (§4.3). Parentheses in types are used for grouping. We assume that objects and packages also implicitly define a class (of the same name as the object or package, but inaccessible to user programs).</p> <p>Non-value types capture properties of identifiers that are not values (§3.3). For example, a type constructor (§3.3.3) does not directly specify the type of values. However, when a type constructor is applied to the correct type arguments, it yields a first-order type, which may be a value type. Non-value types are expressed indirectly in Scala. E.g., a method type is described by writing down a method signature, which in itself is not a real type, although it gives rise to a corresponding function type (§3.3.1). Type constructors are another example, as one can write type Swap[m[_, _], a,b] = m[b, a], but there is no syntax to write the corresponding anonymous type function directly.</p> </blockquote> <p><code>List</code> is a type constructor. You can apply the type <code>Int</code> to get a Value Type, <code>List[Int]</code>, which can classify a value. Other type constructors take more than one parameter.</p> <p>The trait <code>scalaz.MA</code> requires that it's first type parameter must be a type constructor that takes a single type to return a value type, with the syntax <code>trait MA[M[_], A] {}</code>. The type parameter definition describes the shape of the type constructor, which is referred to as its Kind. <code>List</code> is said to have the kind '<code>* -&gt; *</code>.</p> <h3>Partial Application of Types</h3> <p>But how can <code>MA</code> wrap a values of type <code>Validation[X, Y]</code>? The type <code>Validation</code> has a kind <code>(* *) -&gt; *</code>, and could only be passed as a type argument to a type parameter declared like <code>M[_, _]</code>. </p> <p>This implicit conversion in <a href="http://scalaz.googlecode.com/svn/continuous/latest/browse.sxr/scalaz/Scalaz.scala.html#22849" rel="noreferrer">object Scalaz</a> converts a value of type <code>Validation[X, Y]</code> to a <code>MA</code>:</p> <pre><code>object Scalaz { implicit def ValidationMA[A, E](v: Validation[E, A]): MA[PartialApply1Of2[Validation, E]#Apply, A] = ma[PartialApply1Of2[Validation, E]#Apply, A](v) } </code></pre> <p>Which in turn uses a trick with a type alias in <a href="http://scalaz.googlecode.com/svn/continuous/latest/browse.sxr/scalaz/PartialApply1Of2.scala.html" rel="noreferrer">PartialApply1Of2</a> to partially apply the type constructor <code>Validation</code>, fixing the type of the errors, but leaving the type of the success unapplied.</p> <p><code>PartialApply1Of2[Validation, E]#Apply</code> would be better written as <code>[X] =&gt; Validation[E, X]</code>. I recently proposed to add such a syntax to Scala, it might happen in 2.9.</p> <p>Think of this as a type level equivalent of this:</p> <pre><code>def validation[A, B](a: A, b: B) = ... def partialApply1Of2[A, B C](f: (A, B) =&gt; C, a: A): (B =&gt; C) = (b: B) =&gt; f(a, b) </code></pre> <p>This lets you combine <code>Validation[String, Int]</code> with a <code>Validation[String, Boolean]</code>, because the both share the type constructor <code>[A] Validation[String, A]</code>.</p> <h3>Applicative Functors</h3> <p><code>&lt;**&gt;</code> demands the the type constructor <code>M</code> must have associated instances of <a href="http://scalaz.googlecode.com/svn/continuous/latest/browse.sxr/scalaz/Apply.scala.html" rel="noreferrer">Apply</a> and <a href="http://scalaz.googlecode.com/svn/continuous/latest/browse.sxr/scalaz/Functor.scala.html" rel="noreferrer">Functor</a>. This constitutes an Applicative Functor, which, like a Monad, is a way to structure a computation through some effect. In this case the effect is that the sub-computations can fail (and when they do, we accumulate the failures).</p> <p>The container <code>Validation[NonEmptyList[String], A]</code> can wrap a pure value of type <code>A</code> in this 'effect'. The <code>&lt;**&gt;</code> operator takes two effectful values, and a pure function, and combines them with the Applicative Functor instance for that container.</p> <p>Here's how it works for the <code>Option</code> applicative functor. The 'effect' here is the possibility of failure.</p> <pre><code>val os: Option[String] = Some("a") val oi: Option[Int] = Some(2) val result1 = (os &lt;**&gt; oi) { (s: String, i: Int) =&gt; s * i } assert(result1 == Some("aa")) val result2 = (os &lt;**&gt; (None: Option[Int])) { (s: String, i: Int) =&gt; s * i } assert(result2 == None) </code></pre> <p>In both cases, there is a pure function of type <code>(String, Int) =&gt; String</code>, being applied to effectful arguments. Notice that the result is wrapped in the same effect (or container, if you like), as the arguments.</p> <p>You can use the same pattern across a multitude of containers that have an associated Applicative Functor. All Monads are automatically Applicative Functors, but there are even more, like <code>ZipStream</code>.</p> <p><code>Option</code> and <code>[A]Validation[X, A]</code> are both Monads, so you could also used <code>Bind</code> (aka flatMap):</p> <pre><code>val result3 = oi flatMap { i =&gt; os map { s =&gt; s * i } } val result4 = for {i &lt;- oi; s &lt;- os} yield s * i </code></pre> <h3>Tupling with `&lt;|**|&gt;`</h3> <p><code>&lt;|**|&gt;</code> is really similar to <code>&lt;**&gt;</code>, but it provides the pure function for you to simply build a Tuple2 from the results. <code>(_: A, _ B)</code> is a shorthand for <code>(a: A, b: B) =&gt; Tuple2(a, b)</code></p> <h3>And beyond</h3> <p>Here's our bundled examples for <a href="http://scalaz.googlecode.com/svn/continuous/latest/browse.sxr/scalaz/example/ExampleApplicative.scala.html" rel="noreferrer">Applicative</a> and <a href="http://scalaz.googlecode.com/svn/continuous/latest/browse.sxr/scalaz/example/ExampleValidation.scala.html" rel="noreferrer">Validation</a>. I used a slightly different syntax to use the Applicative Functor, <code>(fa ⊛ fb ⊛ fc ⊛ fd) {(a, b, c, d) =&gt; .... }</code></p> <h3>UPDATE: But what happens in the Failure Case?</h3> <blockquote> <p><em>what is happening to the Tuple2/Pair in the failure case</em>?</p> </blockquote> <p>If any of the sub-computations fails, the provided function is never run. It only is run if all sub-computations (in this case, the two arguments passed to <code>&lt;**&gt;</code>) are successful. If so, it combines these into a <code>Success</code>. Where is this logic? This defines the <code>Apply</code> instance for <code>[A] Validation[X, A]</code>. We require that the type X must have a <code>Semigroup</code> avaiable, which is the strategy for combining the individual errors, each of type <code>X</code>, into an aggregated error of the same type. If you choose <code>String</code> as your error type, the <code>Semigroup[String]</code> concatenates the strings; if you choose <code>NonEmptyList[String]</code>, the error(s) from each step are concatenated into a longer <code>NonEmptyList</code> of errors. This concatenation happens below when two <code>Failures</code> are combined, using the <code>⊹</code> operator (which expands with implicits to, for example, <code>Scalaz.IdentityTo(e1).⊹(e2)(Semigroup.NonEmptyListSemigroup(Semigroup.StringSemigroup))</code>.</p> <pre><code>implicit def ValidationApply[X: Semigroup]: Apply[PartialApply1Of2[Validation, X]#Apply] = new Apply[PartialApply1Of2[Validation, X]#Apply] { def apply[A, B](f: Validation[X, A =&gt; B], a: Validation[X, A]) = (f, a) match { case (Success(f), Success(a)) =&gt; success(f(a)) case (Success(_), Failure(e)) =&gt; failure(e) case (Failure(e), Success(_)) =&gt; failure(e) case (Failure(e1), Failure(e2)) =&gt; failure(e1 ⊹ e2) } } </code></pre> <h3>Monad or Applicative, how shall I choose?</h3> <p>Still reading? (<em>Yes. Ed</em>)</p> <p>I've shown that sub-computations based on <code>Option</code> or <code>[A] Validation[E, A]</code> can be combined with either <code>Apply</code> or with <code>Bind</code>. When would you choose one over the other?</p> <p>When you use <code>Apply</code>, the structure of the computation is fixed. All sub-computations will be executed; the results of one can't influence the the others. Only the 'pure' function has an overview of what happened. Monadic computations, on the other hand, allow the first sub-computation to influence the later ones.</p> <p>If we used a Monadic validation structure, the first failure would short-circuit the entire validation, as there would be no <code>Success</code> value to feed into the subsequent validation. However, we are happy for the sub-validations to be independent, so we can combine them through the Applicative, and collect all the failures we encounter. The weakness of Applicative Functors has become a strength!</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload