Function syntax puzzler in scalaz - scala

Following watching Nick Partidge's presentation on deriving scalaz, I got to looking at this example, which is just awesome:
import scalaz._
import Scalaz._
def even(x: Int) : Validation[NonEmptyList[String], Int]
= if (x % 2 ==0) x.success else "not even: %d".format(x).wrapNel.fail
println( even(3) <|*|> even(5) ) //prints: Failure(NonEmptyList(not even: 3, not even: 5))
I was trying to understand what the <|*|> method was doing, here is the source code:
def <|*|>[B](b: M[B])(implicit t: Functor[M], a: Apply[M]): M[(A, B)]
= <**>(b, (_: A, _: B))
OK, that is fairly confusing (!) - but it references the <**> method, which is declared thus:
def <**>[B, C](b: M[B], z: (A, B) => C)(implicit t: Functor[M], a: Apply[M]): M[C]
= a(t.fmap(value, z.curried), b)
So I have a few questions:
How come the method appears to take a higher-kinded type of one type parameter (M[B]) but can get passed a Validation (which has two type paremeters)?
The syntax (_: A, _: B) defines the function (A, B) => Pair[A,B] which the 2nd method expects: what is happening to the Tuple2/Pair in the failure case? There's no tuple in sight!

Type Constructors as Type Parameters
M is a type parameter to one of Scalaz's main pimps, MA, 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 Functor and Apply, which are implicit requirements to the method <**>.
trait MA[M[_], A] {
val value: M[A]
def <**>[B, C](b: M[B], z: (A, B) => C)(implicit t: Functor[M], a: Apply[M]): M[C] = ...
}
What is a Type Constructor?
From the Scala Language Reference:
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).
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.
List is a type constructor. You can apply the type Int to get a Value Type, List[Int], which can classify a value. Other type constructors take more than one parameter.
The trait scalaz.MA 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 trait MA[M[_], A] {}. The type parameter definition describes the shape of the type constructor, which is referred to as its Kind. List is said to have the kind '* -> *.
Partial Application of Types
But how can MA wrap a values of type Validation[X, Y]? The type Validation has a kind (* *) -> *, and could only be passed as a type argument to a type parameter declared like M[_, _].
This implicit conversion in object Scalaz converts a value of type Validation[X, Y] to a MA:
object Scalaz {
implicit def ValidationMA[A, E](v: Validation[E, A]): MA[PartialApply1Of2[Validation, E]#Apply, A] = ma[PartialApply1Of2[Validation, E]#Apply, A](v)
}
Which in turn uses a trick with a type alias in PartialApply1Of2 to partially apply the type constructor Validation, fixing the type of the errors, but leaving the type of the success unapplied.
PartialApply1Of2[Validation, E]#Apply would be better written as [X] => Validation[E, X]. I recently proposed to add such a syntax to Scala, it might happen in 2.9.
Think of this as a type level equivalent of this:
def validation[A, B](a: A, b: B) = ...
def partialApply1Of2[A, B C](f: (A, B) => C, a: A): (B => C) = (b: B) => f(a, b)
This lets you combine Validation[String, Int] with a Validation[String, Boolean], because the both share the type constructor [A] Validation[String, A].
Applicative Functors
<**> demands the the type constructor M must have associated instances of Apply and Functor. 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).
The container Validation[NonEmptyList[String], A] can wrap a pure value of type A in this 'effect'. The <**> operator takes two effectful values, and a pure function, and combines them with the Applicative Functor instance for that container.
Here's how it works for the Option applicative functor. The 'effect' here is the possibility of failure.
val os: Option[String] = Some("a")
val oi: Option[Int] = Some(2)
val result1 = (os <**> oi) { (s: String, i: Int) => s * i }
assert(result1 == Some("aa"))
val result2 = (os <**> (None: Option[Int])) { (s: String, i: Int) => s * i }
assert(result2 == None)
In both cases, there is a pure function of type (String, Int) => String, being applied to effectful arguments. Notice that the result is wrapped in the same effect (or container, if you like), as the arguments.
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 ZipStream.
Option and [A]Validation[X, A] are both Monads, so you could also used Bind (aka flatMap):
val result3 = oi flatMap { i => os map { s => s * i } }
val result4 = for {i <- oi; s <- os} yield s * i
Tupling with `<|**|>`
<|**|> is really similar to <**>, but it provides the pure function for you to simply build a Tuple2 from the results. (_: A, _ B) is a shorthand for (a: A, b: B) => Tuple2(a, b)
And beyond
Here's our bundled examples for Applicative and Validation. I used a slightly different syntax to use the Applicative Functor, (fa ⊛ fb ⊛ fc ⊛ fd) {(a, b, c, d) => .... }
UPDATE: But what happens in the Failure Case?
what is happening to the Tuple2/Pair in the failure case?
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 <**>) are successful. If so, it combines these into a Success. Where is this logic? This defines the Apply instance for [A] Validation[X, A]. We require that the type X must have a Semigroup avaiable, which is the strategy for combining the individual errors, each of type X, into an aggregated error of the same type. If you choose String as your error type, the Semigroup[String] concatenates the strings; if you choose NonEmptyList[String], the error(s) from each step are concatenated into a longer NonEmptyList of errors. This concatenation happens below when two Failures are combined, using the ⊹ operator (which expands with implicits to, for example, Scalaz.IdentityTo(e1).⊹(e2)(Semigroup.NonEmptyListSemigroup(Semigroup.StringSemigroup)).
implicit def ValidationApply[X: Semigroup]: Apply[PartialApply1Of2[Validation, X]#Apply] = new Apply[PartialApply1Of2[Validation, X]#Apply] {
def apply[A, B](f: Validation[X, A => B], a: Validation[X, A]) = (f, a) match {
case (Success(f), Success(a)) => success(f(a))
case (Success(_), Failure(e)) => failure(e)
case (Failure(e), Success(_)) => failure(e)
case (Failure(e1), Failure(e2)) => failure(e1 ⊹ e2)
}
}
Monad or Applicative, how shall I choose?
Still reading? (Yes. Ed)
I've shown that sub-computations based on Option or [A] Validation[E, A] can be combined with either Apply or with Bind. When would you choose one over the other?
When you use Apply, 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.
If we used a Monadic validation structure, the first failure would short-circuit the entire validation, as there would be no Success 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!

Related

Scala upper bound notation accepts all types (not only super type)

In Scala's upper bound concept, the given type or its super type can be passed. For example, in the below method S is the type and A is the parameter we pass. This method accepts all the values present in Scala's type system actually. S, S subtype and its super type. This is due to the fact that all types extends Any type.
def method[A >: S](a:A) = { ... }
Then why can't we write all the upper bound notations as Any (which is the universal type in Scala). The above definition can be re-written as:
def met(a:Any) = { ... }
This is easy to understand.
What sort of advantage the upperbound brings in ?
Thanks!
It allows you to lose less type information than you would by going to Any.
For example If you have Dog and Cat inherit Animal, this works:
val maybeDog: Option[Dog] = ???
val pet = maybeDog.getOrElse(Cat())
Because getOrElse has a signature of def getOrElse[B >: A](default: => B): B, it is inferred that B is Animal (as the least upper bound of Cat and Dog), so the static type of val pet is Animal. If it was using Any, the result would require unsafe casting to work further. If it was not introducing a new type parameter altogether, you would be forced to write (maybeDog: Option[Animal]).getOrElse(Cat()) to achieve the same unification.
Additionally, it restricts the implementation to not do something completely silly. For example, this typechecks:
def getOrElse[A](option: Option[A])(default: => Any): Any = 42 // Int is Any, so why not?
While this doesn't:
def getOrElse[A, B >: A](option: Option[A])(default: => B): B = 42
Because while anything can go as B, that doesn't imply that Int is always a subtype of B.

How does flatmap really work in Scala

I took the scala odersky course and thought that the function that Flatmap takes as arguments , takes an element of Monad and returns a monad of different type.
trait M[T] {
def flatMap[U](f: T => M[U]): M[U]
}
On Monad M[T] , the return type of function is also the same Monad , the type parameter U might be different.
However I have seen examples on internet , where the function returns a completely different Monad. I was under impression that return type of function should the same Monad. Can someone simplify the below to explain how flapmap results in the actual value instead of Option in the list.
Is the List not a Monad in Scala.
val l= List(1,2,3,4,5)
def f(x:int) = if (x>2) Some(x) else None
l.map(x=>f(x))
//Result List[Option[Int]] = List( None , None , Some(3) , Some(4) , Some(5))
l.flatMap(x=>f(x))
//Result: List(3,4,5)
Let's start from the fact that M[T]is not a monad by itself. It's a type constructor. It becomes a monad when it's associated with two operators: bind and return (or unit). There are also monad laws these operators must satisfy, but let's omit them for brevity. In Haskell the type of bind is:
class Monad m where
...
(>>=) :: m a -> (a -> m b) -> m b
where m is a type constructor. Since Scala is OO language bind will look like (first argument is self):
trait M[T] {
def bind[U](f: T => M[U]): M[U]
}
Here M === m, T === a, U === b. bind is often called flatMap. In a pure spherical world in a vacuum that would be a signature of flatMap in OO language. Scala is a very practical language, so the real signature of flatMap for List is:
final def flatMap[B, That](f: (A) ⇒ GenTraversableOnce[B])(implicit bf: CanBuildFrom[List[A], B, That]): That
It's not bind, but will work as a monadic bind if you provide f in the form of (A) => List[B] and also make sure that That is List[B]. On the other hand Scala is not going to watch your back if you provide something different, but will try to find some meaningful conversion (e.g. CanBuildFrom or something else) if it exists.
UPDATE
You can play with scalac flags (-Xlog-implicits, -Xlog-implicit-conversions) to see what's happening:
scala> List(1).flatMap { x => Some(x) }
<console>:1: inferred view from Some[Int] to scala.collection.GenTraversableOnce[?] via scala.this.Option.option2Iterable[Int]: (xo: Option[Int])Iterable[Int]
List(1).flatMap { x => Some(x) }
^
res1: List[Int] = List(1)
Hmm, perhaps confusingly, the signature you gave is not actually correct, since it's really (in simplified form):
def flatMap[B](f: (A) ⇒ GenTraversableOnce[B]): Traversable[B]
Since the compiler is open-source, you can actually see what it's doing (with its full signature):
def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
def builder = bf(repr) // extracted to keep method size under 35 bytes, so that it can be JIT-inlined
val b = builder
for (x <- this) b ++= f(x).seq
b.result
}
So you can see that there is actually no requirement that the return type of f be the same as the return type of flatMap.
The flatmap found in the standard library is a much more general and flexible method than the monadic bind method like the flatMap from Odersky's example.
For example, the full signature of flatmap on List is
def flatMap[B, That](f: (A) ⇒ GenTraversableOnce[B])(implicit bf: CanBuildFrom[List[A], B, That]): That
Instead of requiring the function passed into flatmap to return a List, it is able to return any GenTraversableOnce object, a very generic type.
flatmap then uses the implicit CanBuildFrom mechanism to determine the appropriate type to return.
So when you use flatmap with a function that returns a List, it is a monadic bind operation, but it lets you use other types as well.

Curry in scala with parametric types

The authors of Functional Programming in Scala give this as the definition of curry in scala:
def curry[A,B,C](f: (A, B) => C): A => (B => C) =
a => b => f(a, b)
However, if we apply it to a function taking parametric types, e.g.:
def isSorted[A](as: Array[A], ordered:(A,A)=>Boolean) =
if(as.size < 2)
true else
as.zip(as.drop(1)).map(ordered.tupled).reduce(_ && _)
Then the result wants A (in isSorted) to be nothing:
scala> curry(isSorted)
res29: Array[Nothing] => (((Nothing, Nothing) => Boolean) => Boolean) = <function1>
This is obviously not what is desired. Should curry be defined differently, or called differently, or is it not practical to implement curry in Scala?
You're running into two separate problems here. The first is that isSorted when it is passed to curry is forced to become monomorphic. The second is that Scala's type inference is failing you here.
This is one of those times where the difference between a function and a method matters in Scala. isSorted is eta-expanded into a function which in turn is a Scala value, not a method. Scala values are always monomorphic, only methods can be polymorphic. For any method of types (A, B) C (this is the syntax for a method type and is different from (A, B) => C which is a function and therefore a value), the default eta-expansion is going to result in the superclass of all functions of that arity, namely (Nothing, Nothing) => Any. This is responsible for all the Nothings you see (you don't have any Anys because isSorted is monomorphic in its return value).
You might imagine despite the monomorphic nature of Scala values though, that you could ideally do something like
def first[A, B](x: A, y: B): A = x
curry(first)(5)(6) // This doesn't compile
This is Scala's local type inference biting you. It works on separate parameter lists from left to right first is the first thing to get a type inferred and as mentioned above, it gets inferred to be (Nothing, Nothing) => Any. This clashes with Ints that follow.
As you've realized, one way of getting around this is annotating your polymorphic method that you pass to curry so that it eta-expands into the correct type. This is almost certainly the way to go.
Another thing you could possibly do (although I'm don't think it'll serve anything except pedagogical purposes) is to curry curry itself and define it as follows:
def curryTwo[A, B, C](x: A)(y: B)(f: (A, B) => C): C = f(x, y)
On the one hand, the below works now because of the left-to-right type inference.
curryTwo(5)(6)(first) // 5
On the other hand, to use curryTwo in the scenarios where you'd want to use curry, you're going to need to need to provide types to Scala's type inference engine anyway.
It turns out I can call curry like this:
curry(isSorted[Int])
Which yields:
scala> curry(isSorted[Int])
res41: Array[Int] => (((Int, Int) => Boolean) => Boolean) = <function1>
See https://stackoverflow.com/a/4593509/21640

Scala Option type upper bound don't understand

I'm reading Functional Programming in Scala, and in chapter 04 the authors implement Option on their own. Now, when defining the function getOrElse they use an upper bound to restrict the type of A to a supertype (if a understood correctly)
So, the definition goes:
sealed trait Option[+A] {
def getOrElse[B >: A](default: => B): B = this match {
case None => default
case Some(a) => a
}
}
So, when we have something like
val a = Some(4)
println(a.getOrElse(None)) => println prints a integer value
val b = None
println(b.getOrElse(Some(3)) => println prints a Option[Integer] value
a has type Option[Int], so A would be type Int. B would be type Nothing. Nothing is a subtype of every other type. That means that Option[Nothing] is a subtype of Option[Int] (because of covariance), right?
But with B >: A we said that B has to be a supertype?! So how can we get an Int back? This is a bit confusing for me...
Anyone care to try and clarify?
That means that Option[Nothing] is a subtype of Option[Int] (because of covariance), right?
Correct. Option[Nothing] is an Option[Int].
But with B >: A we said that B has to be a supertype?! So how can we get an Int back?
It doesn't have to be a super-type. It just requires A as a lower-bound. Which means you can still pass Int to getOrElse if A is Int.
But that doesn't mean you can't pass instances of a sub-class. For instance:
class A
class B extends A
class C extends B
scala> Option(new B)
res196: Option[B] = Some(B#661f82ac)
scala> res196.getOrElse(new C)
res197: B = B#661f82ac
scala> res196.getOrElse(new A)
res198: A = B#661f82ac
scala> res196.getOrElse("...")
res199: Object = B#661f82ac
I can still pass an instance of C, because C can be up-cast to B. I can also pass a type higher up the inheritance tree, and getOrElse will return that type, instead. If I pass a type that has nothing to do with the type contained in the Option, then the type with the least upper-bound will be inferred. In the above case, it's Any.
So why is the lower-bound there at all? Why not have:
def getOrElse[B <: A](default: => B): B
This won't work because getOrElse must either return the A that's contained in the Option, or the default B. But if we return the A, and A is not a B, so the type-bound is invalid. Perhaps if getOrElse returned A:
def getOrElse[B <: A](default: => B): A
This would work (if it were really defined that way), but you would be restricted by the type-bounds. So in my above example, you could only pass B or C to getOrElse on an Option[B]. In any case, this is not how it is in the standard library.
The standard library getOrElse allows you to pass anything to it. Say you have Option[A]. If we pass a sub-type of A, then it is up-cast to A. If we pass A, obviously this is okay. And if we pass some other type, then the compiler infers the least upper-bound between the two. In all cases, the type-bound B >: A is met.
Because getOrElse allows you to pass anything to it, many consider it very tricky. For example you could have:
val number = "blah"
// ... lots of code
val result = Option(1).getOrElse(number)
And this will compile. We'll just have an Option[Any] that will probably cause an error somewhere else down the line.

type parameter definition in scala [duplicate]

Sometime I stumble into the semi-mysterious notation of
def f[T](..) = new T[({type l[A]=SomeType[A,..]})#l] {..}
in Scala blog posts, which give it a "we used that type-lambda trick" handwave.
While I have some intutition about this (we gain an anonymous type parameter A without having to pollute the definition with it?), I found no clear source describing what the type lambda trick is, and what are its benefits. Is it just syntactic sugar, or does it open some new dimensions?
Type lambdas are vital quite a bit of the time when you are working with higher-kinded types.
Consider a simple example of defining a monad for the right projection of Either[A, B]. The monad typeclass looks like this:
trait Monad[M[_]] {
def point[A](a: A): M[A]
def bind[A, B](m: M[A])(f: A => M[B]): M[B]
}
Now, Either is a type constructor of two arguments, but to implement Monad, you need to give it a type constructor of one argument. The solution to this is to use a type lambda:
class EitherMonad[A] extends Monad[({type λ[α] = Either[A, α]})#λ] {
def point[B](b: B): Either[A, B]
def bind[B, C](m: Either[A, B])(f: B => Either[A, C]): Either[A, C]
}
This is an example of currying in the type system - you have curried the type of Either, such that when you want to create an instance of EitherMonad, you have to specify one of the types; the other of course is supplied at the time you call point or bind.
The type lambda trick exploits the fact that an empty block in a type position creates an anonymous structural type. We then use the # syntax to get a type member.
In some cases, you may need more sophisticated type lambdas that are a pain to write out inline. Here's an example from my code from today:
// types X and E are defined in an enclosing scope
private[iteratee] class FG[F[_[_], _], G[_]] {
type FGA[A] = F[G, A]
type IterateeM[A] = IterateeT[X, E, FGA, A]
}
This class exists exclusively so that I can use a name like FG[F, G]#IterateeM to refer to the type of the IterateeT monad specialized to some transformer version of a second monad which is specialized to some third monad. When you start to stack, these kinds of constructs become very necessary. I never instantiate an FG, of course; it's just there as a hack to let me express what I want in the type system.
The benefits are exactly the same as those conferred by anonymous functions.
def inc(a: Int) = a + 1; List(1, 2, 3).map(inc)
List(1, 2, 3).map(a => a + 1)
An example usage, with Scalaz 7. We want to use a Functor that can map a function over the second element in a Tuple2.
type IntTuple[+A]=(Int, A)
Functor[IntTuple].map((1, 2))(a => a + 1)) // (1, 3)
Functor[({type l[a] = (Int, a)})#l].map((1, 2))(a => a + 1)) // (1, 3)
Scalaz provides some implicit conversions that can infer the type argument to Functor, so we often avoid writing these altogether. The previous line can be rewritten as:
(1, 2).map(a => a + 1) // (1, 3)
If you use IntelliJ, you can enable Settings, Code Style, Scala, Folding, Type Lambdas. This then hides the crufty parts of the syntax, and presents the more palatable:
Functor[[a]=(Int, a)].map((1, 2))(a => a + 1)) // (1, 3)
A future version of Scala might directly support such a syntax.
To put things in context: This answer was originally posted in another thread. You are seeing it here because the two threads have been merged. The question statement in the said thread was as follows:
How to resolve this type definition: Pure[({type ?[a]=(R, a)})#?] ?
What are the reasons of using such construction?
Snipped comes from scalaz library:
trait Pure[P[_]] {
def pure[A](a: => A): P[A]
}
object Pure {
import Scalaz._
//...
implicit def Tuple2Pure[R: Zero]: Pure[({type ?[a]=(R, a)})#?] = new Pure[({type ?[a]=(R, a)})#?] {
def pure[A](a: => A) = (Ø, a)
}
//...
}
Answer:
trait Pure[P[_]] {
def pure[A](a: => A): P[A]
}
The one underscore in the boxes after P implies that it is a type constructor takes one type and returns another type. Examples of type constructors with this kind: List, Option.
Give List an Int, a concrete type, and it gives you List[Int], another concrete type. Give List a String and it gives you List[String]. Etc.
So, List, Option can be considered to be type level functions of arity 1. Formally we say, they have a kind * -> *. The asterisk denotes a type.
Now Tuple2[_, _] is a type constructor with kind (*, *) -> * i.e. you need to give it two types to get a new type.
Since their signatures do not match, you cannot substitute Tuple2 for P. What you need to do is partially apply Tuple2 on one of its arguments, which will give us a type constructor with kind * -> *, and we can substitue it for P.
Unfortunately Scala has no special syntax for partial application of type constructors, and so we have to resort to the monstrosity called type lambdas. (What you have in your example.) They are called that because they are analogous to lambda expressions that exist at value level.
The following example might help:
// VALUE LEVEL
// foo has signature: (String, String) => String
scala> def foo(x: String, y: String): String = x + " " + y
foo: (x: String, y: String)String
// world wants a parameter of type String => String
scala> def world(f: String => String): String = f("world")
world: (f: String => String)String
// So we use a lambda expression that partially applies foo on one parameter
// to yield a value of type String => String
scala> world(x => foo("hello", x))
res0: String = hello world
// TYPE LEVEL
// Foo has a kind (*, *) -> *
scala> type Foo[A, B] = Map[A, B]
defined type alias Foo
// World wants a parameter of kind * -> *
scala> type World[M[_]] = M[Int]
defined type alias World
// So we use a lambda lambda that partially applies Foo on one parameter
// to yield a type of kind * -> *
scala> type X[A] = World[({ type M[A] = Foo[String, A] })#M]
defined type alias X
// Test the equality of two types. (If this compiles, it means they're equal.)
scala> implicitly[X[Int] =:= Foo[String, Int]]
res2: =:=[X[Int],Foo[String,Int]] = <function1>
Edit:
More value level and type level parallels.
// VALUE LEVEL
// Instead of a lambda, you can define a named function beforehand...
scala> val g: String => String = x => foo("hello", x)
g: String => String = <function1>
// ...and use it.
scala> world(g)
res3: String = hello world
// TYPE LEVEL
// Same applies at type level too.
scala> type G[A] = Foo[String, A]
defined type alias G
scala> implicitly[X =:= Foo[String, Int]]
res5: =:=[X,Foo[String,Int]] = <function1>
scala> type T = World[G]
defined type alias T
scala> implicitly[T =:= Foo[String, Int]]
res6: =:=[T,Foo[String,Int]] = <function1>
In the case you have presented, the type parameter R is local to function Tuple2Pure and so you cannot simply define type PartialTuple2[A] = Tuple2[R, A], because there is simply no place where you can put that synonym.
To deal with such a case, I use the following trick that makes use of type members. (Hopefully the example is self-explanatory.)
scala> type Partial2[F[_, _], A] = {
| type Get[B] = F[A, B]
| }
defined type alias Partial2
scala> implicit def Tuple2Pure[R]: Pure[Partial2[Tuple2, R]#Get] = sys.error("")
Tuple2Pure: [R]=> Pure[[B](R, B)]