Scala GADT instance Functor - scala

In Haskell I got:
data Foo a where
Bar :: a -> Foo a
Map :: (a -> b) -> Foo a -> Foo b
instance Functor Foo where
fmap = Map
In Scala I came up with:
import cats.Functor
trait Foo[A]
case class Bar[A](t: A) extends Foo[A]
case class Map[A,B](fun: A => B,foo: Foo[A]) extends Foo[B]
implicit val fooFunctor: Functor[Foo] = new Functor[Foo] {
def map[A,B](fa: Foo[A])(f: A => B) = Map(f,fa)
}
But Bar(40).map(_+2) gives me:
error: value map is not a member of Bar[Int]
I fairly new to Scala and don't know the way of inheritance that well.
What am I missing?

You need to upcast Bar(40) to Foo explicitly, and import the syntax implicits:
import cats.syntax.functor._
(Bar(40): Foo[Int]).map(_+2)
You need the upcast because Scala will infer the type Bar[Int] for the expression Bar(40) and this then interferes with finding the appropriate implicit that adds the map method. For this reason you sometimes see helper methods in the companion object to do the upcast for you:
object Foo {
def bar[A](a: A): Foo[A] = Bar(a)
// etc.
}

I thought a little bit about how one could solve this problem. Basically, we want to provide the functor operations even if only a super type is a functor. It seems to be impossible to express, that some higher-kinded type is the super type of an other, e.g. something like this is not possible: def bla[F[_], R[_] <: F]
We can however provide a conversion from R[] to F[] implicitly together with the functor for B:
abstract class ProvidesFor[R,F[_],FF[_[_]],A](val value: FF[F]) {
def convert(r: R): F[A]
}
implicit def providesFunctorForBar[A] =
new ProvidesFor[Bar[A],Foo,Functor,A](Functor[Foo]) {
override def convert(r: Bar[A]): Foo[A] = r
}
So the implict val will provide us with a functor for Foo and a convertion from Bar to Foo.
Now we can provide an implicit converstion to Functor.Ops like this:
implicit class FunctorOps[R[_],F[_],A](target: R[A])(implicit tc: ProvidesFor[R[A],F,Functor,A])
extends Functor.Ops[F,A] {
override val self = tc.convert(target)
override val typeClassInstance = tc.value
override def map[B](f: A => B): F[B] = typeClassInstance.map(self)(f)
override def imap[B](f: A => B)(g: B => A): F[B] = map(f)
}
Now this works as expected:
Bar(1).imap(_+2)(_+5)
We can also do the same for Map:
implicit def providesFunctorForMap[A,B] =
new ProvidesFor[Map[A,B],Foo,Functor,B](Functor[Foo]) {
override def convert(r: Map[A,B]): Foo[B] = r
}
Map((_:Int) + 1,Bar(5)).map(_+2)
For some strange reason I had to implement map and imap when extending Functor.Ops even though these methods are not abstract. In fact it compiles fine when I do not implement them but it fails at runtime with an AbstractMethodError. So somehow the compiler thinks the implementations are there but they are not. I suspect they are using some kind of byte code optimization tool that removes those implementations.

Related

Implement trait methods using subclasses' types

I want a trait Foo to provide transform method that would apply a function to it. Also, I want to force implementing classes to have an increment method that would somehow transform the object as well. Naive solution:
trait Foo {
def transform(fun: Foo => Foo): Foo = fun(this)
def increment(n: Int): Foo
}
case class A(a: Int) extends Foo {
// expecting available: transform(fun: A => A): A
// to be implemented: increment(n: Int): A
...
}
Above won't work... Inherited transform still expects Foo => Foo, not A => A and increment still wants to return Foo, not A.
One more attempt:
trait Foo {
def transform[C <: Foo](fun: C => C): C = fun(this.asInstanceOf[C])
def increment[C <: Foo](n: Int): C
}
case class A(a: Int) extends Foo {
def increment(n: Int) = A(a + n)
}
A will not compile - it will still complain about the signature.
Taking out the increment function, transform works. However asInstanceOf looks a bit unsafe. Also, I need to explicitly provide type parameter to transform:
val a = A(1)
a.transform[A](x => x.copy(x.a + 1)) // returns A(2)
I wonder if there's a smart way to have it done.
The most direct way of getting what you want is to move the type parameter up to the trait declaration. That gives trait Foo[C]{...}. However, using copy in your transform still won't work, since the Foo trait doesn't know anything about anything that extends it. You can give it a bit more information with self typing:
trait Foo[C] {
this: C =>
def transform(fun: C => C): C = fun(this)
def increment(n: Int): C
}
case class A(a: Int) extends Foo[A] {
def increment(n: Int) = A(a + n)
}
The A extends Foo[A] is a little awkward to use here, but it works, since now when you extend Foo, it provides that type information back to the trait. That's still a little bit awkward though. It turns out there's a technique called type classes that we can use here to potentially improve things. First, you set up your trait. In a type class, there is exactly one implementation of the trait per type, so each method should also take in the instance that you want to operate on:
trait Foo[C] {
def transform(c: C)(f: C => C): C
def increment(c: C, inc: Int): C
}
Next, in the companion object you set up instances of the typeclass for the types you care about:
case class A(a: Int)
object Foo {
implicit val ATransform = new Foo[A] {
def transform (base: A)(f: A => A) = f(base)
def increment(base: A, inc: Int) = A(base.a+inc)
}
//Convenience function for finding the instance for a type.
//With this, Foo[A] is equivalent to implicitly[Foo[A]]
def apply[C](implicit foo: Foo[C]) = foo
}
Now we can use the type class as follows:
val b = A(3)
Foo[A].transform(b)(x=>x.copy(a=x.a+1)) //A(4)
Foo[A].increment(b,5) //A(8)

Scalaz instancing typeclass and case class

This problem is pretty hard to explain. I try to implement a kind of Arrow, call it MyArr, which extends the Arrow trait from scalaz. However, MyArr is also a kind of Algbraic Data Type, so I make a few case classes out of if, and wrote down code like this(minimal example):
package org.timeless
import scalaz._
import Scalaz._
import std.option._, std.list._
sealed trait MyArr[A,B] extends Arrow[MyArr] {
def id[A]: MyArr[A,A] = SId()
def compose[A,B,C](s1: MyArr[B,C], s2: MyArr[A,B]): MyArr[A,C] =
SRight(s2, s1)
def arr[A,B](f: A=>B): MyArr[A,B] = SPure(f)
def first[A,B,C](s: MyArr[A,B]): MyArr[(A,C),(B,C)] = SPar(s, SId())
}
case class SId[A] () extends MyArr[A,A]()
case class SRight[M[_],A,B,C](s1: MyArr[A,B], s2: MyArr[B,C]) extends MyArr[A,C]
case class SPure[A,B](f: A=>B) extends MyArr[A,B]
case class SPar[M[_],A,B,C,D](s1: MyArr[A,B], s2: MyArr[C,D]) extends MyArr[(A,C),(B,D)]
object MyArr {
val b = SId[Int]()
val c = SId[Int]()
// val a: MyArr[Int,Int] = id[Int] // Error
// val d = c compose b // Error
// val d = b >>> c // Error
val d = b >>> (b,c) // ??? Arguments
}
As easily seen, the id function is actually the constructor of SId, etc. The classes themselves compile fine, but I don't see any way to actually use it as an Arrow. I actually came from Haskell programming, so I might be doing it totally wrong, but equivalent code in Haskell should be like this(with GADTs):
data MyArr a b where
SId :: MyArr a b
SRight :: MyArr a b -> MyArr b c -> MyArr a c
SPure :: (a -> b) -> MyArr a b
SPar :: MyArr a b -> MyArr c d -> MyArr (a,c) (b,d)
instance Category MyArr where
id = SId
(.) = SRight
instance Arrow MyArr where
arr = SPure
first s = SPar s SId
Typeclasses in Scala
Typeclasses in Scala are not built into the language like in Haskell. They are just a design pattern and are usually implemented with the help of implicit arguments:
def pure[M[_], T](
implicit monad: Monad[M] // Fetching a monad instance for type M
): M[T] =
monad.pure[T] // Using methods of the monad instance
You don't have to extend the typeclass trait to provide a typeclass instance for some ADT. The typeclass instance has to be defined somewhere as an implicit val, implicit def, implicit object, etc. Then you can import the relevant instance into scope before using it.
There is also a way to supply the typeclass instance automatically, without having to import it explicitly. To do that the instance should be declared in the companion object of either the typeclass class/trait or ADT class/trait, or one of their parent classes/traits; or in a package object in which one of those is defined. You can read more on the topic of implicit resolution in this answer: Where does Scala look for implicits?
Defining a typeclass instance
So to get back to your problem, you can define your ADT like this:
sealed trait MyArr[A,B]
case class SId[A] () extends MyArr[A,A]()
case class SRight[M[_],A,B,C](s1: MyArr[A,B], s2: MyArr[B,C]) extends MyArr[A,C]
case class SPure[A,B](f: A=>B) extends MyArr[A,B]
case class SPar[M[_],A,B,C,D](s1: MyArr[A,B], s2: MyArr[C,D]) extends MyArr[(A,C),(B,D)]
And provide the Arrow instance in the companion object of MyArr:
object MyArr {
implicit val arrow: Arrow[MyArr] = new Arrow[MyArr] {
def id[A]: MyArr[A,A] = SId()
def compose[A,B,C](s1: MyArr[B,C], s2: MyArr[A,B]): MyArr[A,C] =
SRight(s2, s1)
def arr[A,B](f: A=>B): MyArr[A,B] = SPure(f)
def first[A,B,C](s: MyArr[A,B]): MyArr[(A,C),(B,C)] = SPar(s, SId())
}
def apply[T]: MyArr[T, T] = arrow.id[T]
}
Using the typeclass instance
I believe it's not possible to provide a generic id function (or return, pure, etc.) in Scala due to some limitations of Scala's type inference.
Instead you can use the MyArr.apply method defined above:
val a: MyArr[Int,Int] = MyArr[Int]
As the ADT doesn't extend the typeclass, it doesn't inherit its methods like compose or >>>. They can be provided separately using the 'Pimp My Library' pattern.
Indeed, the >>> method in scalaz comes from the ComposeOps class, which is defined like this:
final class ComposeOps[F[_, _],A, B] private[syntax]
(self: F[A, B])
(val F: Compose[F])
extends Ops[F[A, B]]
And there is an implicit conversion defined from some type F[_, _] to this class ComposeOps, if there as a Compose instance available for F:
implicit def ToComposeOps[F[_, _],A, B](v: F[A, B])(implicit F0: Compose[F])
This conversion is imported with import Scalaz._, and that's why this line works now:
val d = b >>> c
But there is no extension in scalaz that provides a compose method on ADTs with an Arrow instance, so this line still gives an error:
val e = c compose b
To make it work, you can provide an extension yourself. A simple example could look like this:
// implicit class is equivalent to a normal class
// with an implicit conversion to this class
implicit class ArrowOps[T[_, _], A, B](f: T[A, B])(implicit arrow: Arrow[T]) {
def compose[C](g: T[C, A]): T[C, B] = arrow.compose(f, g)
}

Context bounds for generic polymorphic data in collection

I have the simplified situation:
abstract sealed trait Top
class A[T] extends Top
class B[T] extends Top
class Typeclass[T]
implicit def a[T] = new Typeclass[A[T]]
implicit def b[T] = new Typeclass[B[T]]
Now I have a Map[String, Top] and want to use an operation on all values in the map that require the presence of an instance of Typeclass to be available in the context. This will not compile as the concrete types of the values in the map are not visible from its type and I can therefore not set a context bound for them.
Is there a way to tell the compiler that in fact there will always be an instance available? In this example this is given as there are implicit functions to generate those instances for every concrete subtype of Top.
Or is the only solution to use a HList and recurse over its type requiring all the instances to be in context?
I recommend using some variation on this adaptation of Oleg's Existentials as universals in this sort of situation ... pack the the type class instance along with the value it's the instance for,
abstract sealed trait Top
class A[T] extends Top
class B[T] extends Top
class Typeclass[T]
implicit def a[T] = new Typeclass[A[T]]
implicit def b[T] = new Typeclass[B[T]]
trait Pack {
type T <: Top
val top: T
implicit val tc: Typeclass[T]
}
object Pack {
def apply[T0 <: Top](t0: T0)(implicit tc0: Typeclass[T0]): Pack =
new Pack { type T = T0 ; val top = t0 ; val tc = tc0 }
}
val m = Map("a" -> Pack(new A[Int]), "b" -> Pack(new B[Double]))
def foo[T: Typeclass](t: T): Unit = ()
def bar(m: Map[String, Pack], k: String): Unit =
m.get(k).map { pack =>
import pack._ // imports T, top and implicit tc
foo(top) // instance available for call of foo
}
bar(m, "a")
As discussed in comment it would be more convenient to have the typeclass defined on Top, and it might be done with pattern matching.
supposing part of the definition of the typeclass is
def f[T](t: T): FResult[T],
and you have the corresponding implentations
def fOnA[T](t: A[T]): FResult[A[T]] = ...
def fOnB[T](t: B[T]): FResult[B[T]] = ...
Then you can define
def fOnT(t: Top) : FResult[Top] = t match {
case a: A[_] => fOnA(a)
// provided an FResult[A[T]] is an FResult[Top],
// or some conversion is possible
case b: B[_] => fOnB(b)
}
If is both legal and safe to call a generic method, such as fOnA[T] with an existential (a matching A[_])
However, it might be difficult to convince the compiler that the parameter you pass to f or the result you get are ok, given the reduced information of the existential. If so, please post the signatures you need.

What are the limitations on inference of higher-kinded types in Scala?

In the following simplified sample code:
case class One[A](a: A) // An identity functor
case class Twice[F[_], A](a: F[A], b: F[A]) // A functor transformer
type Twice1[F[_]] = ({type L[α] = Twice[F, α]}) // We'll use Twice1[F]#L when we'd like to write Twice[F]
trait Applicative[F[_]] // Members omitted
val applicativeOne: Applicative[One] = null // Implementation omitted
def applicativeTwice[F[_]](implicit inner: Applicative[F]): Applicative[({type L[α] = Twice[F, α]})#L] = null
I can call applicativeTwice on applicativeOne, and type inference works, as soon as I try to call it on applicativeTwice(applicativeOne), inference fails:
val aOK = applicativeTwice(applicativeOne)
val bOK = applicativeTwice[Twice1[One]#L](applicativeTwice(applicativeOne))
val cFAILS = applicativeTwice(applicativeTwice(applicativeOne))
The errors in scala 2.10.0 are
- type mismatch;
found : tools.Two.Applicative[[α]tools.Two.Twice[tools.Two.One,α]]
required: tools.Two.Applicative[F]
- no type parameters for method applicativeTwice:
(implicit inner: tools.Two.Applicative[F])tools.Two.Applicative[[α]tools.Two.Twice[F,α]]
exist so that it can be applied to arguments
(tools.Two.Applicative[[α]tools.Two.Twice[tools.Two.One,α]])
--- because ---
argument expression's type is not compatible with formal parameter type;
found : tools.Two.Applicative[[α]tools.Two.Twice[tools.Two.One,α]]
required: tools.Two.Applicative[?F]
Why wouldn't "?F" match with anything (of the right kind) ?
Ultimately I'd like applicativeTwice to be an implicit function, but I'd have to get the type inference working first.
I have seen similar questions, and the answers pointed to limitations in the type inference algorithms. But this case seems pretty limitative, and must be quite an annoyance in monad transformers, so I suspect I'm missing some trick to work around this.
You've hit a common annoyance: SI-2712. For clarity, I'm going to minimize your code a bit:
import language.higherKinds
object Test {
case class Base[A](a: A)
case class Recursive[F[_], A](fa: F[A])
def main(args: Array[String]): Unit = {
val one = Base(1)
val two = Recursive(one)
val three = Recursive(two) // doesn't compile
println(three)
}
}
This demonstrates the same type error as yours:
argument expression's type is not compatible with formal parameter type;
found : Test.Recursive[Test.Base,Int]
required: ?F
val three = Recursive(two) // doesn't compile
^
First a bit of syntax and terminology you probably already know:
In Scala we say that a plain, unparameterized data type (such as Int) has kind _. It's monomorphic.
Base, on the other hand, is parameterized. we can't use it as the type of a value without providing the type it contains, so we say has kind _[_]. It's rank-1 polymorphic: a type constructor that takes a type.
Recursive goes further still: it has two parameters, F[_] and A. The number of type parameters don't matter here, but their kinds do. F[_] is rank-1 polymorphic, so Recursive is rank-2 polymorphic: it's a type constructor that takes a type constructor.
We call anything rank two or above higher-kinded, and this is where the fun starts.
Scala in general doesn't have trouble with higher-kinded types. This is one of several key features that distinguishes its type system from, say, Java's. But it does have trouble with partial application of type parameters when dealing with higher-kinded types.
Here's the problem: Recursive[F[_], A] has two type parameters. In your sample code, you did the "type lambda" trick to partially apply the first parameter, something like:
val one = Base(1)
val two = Recursive(one)
val three = {
type λ[α] = Recursive[Base, α]
Recursive(two : λ[Int])
}
This convinces the compiler that you're providing something of the correct kind (_[_]) to the Recursive constructor. If Scala had curried type parameter lists, I'd definitely have used that here:
case class Base[A](a: A)
case class Recursive[F[_]][A](fa: F[A]) // curried!
def main(args: Array[String]): Unit = {
val one = Base(1) // Base[Int]
val two = Recursive(one) // Recursive[Base][Int]
val three = Recursive(two) // Recursive[Recursive[Base]][Int]
println(three)
}
Alas, it does not (see SI-4719). So, to the best of my knowledge, the most common way of dealing with this problem is the "unapply trick," due to Miles Sabin. Here is a greatly simplified version of what appears in scalaz:
import language.higherKinds
trait Unapply[FA] {
type F[_]
type A
def apply(fa: FA): F[A]
}
object Unapply {
implicit def unapply[F0[_[_], _], G0[_], A0] = new Unapply[F0[G0, A0]] {
type F[α] = F0[G0, α]
type A = A0
def apply(fa: F0[G0, A0]): F[A] = fa
}
}
In somewhat hand-wavey terms, this Unapply construct is like a "first-class type lambda." We define a trait representing the assertion that some type FA can be decomposed into a type constructor F[_] and a type A. Then in its companion object, we can define implicits to provide specific decompositions for types of various kinds. I've only defined here the specific one that we need to make Recursive fit, but you could write others.
With this extra bit of plumbing, we can now do what we need:
import language.higherKinds
object Test {
case class Base[A](a: A)
case class Recursive[F[_], A](fa: F[A])
object Recursive {
def apply[FA](fa: FA)(implicit u: Unapply[FA]) = new Recursive(u(fa))
}
def main(args: Array[String]): Unit = {
val one = Base(1)
val two = Recursive(one)
val three = Recursive(two)
println(three)
}
}
Ta-da! Now type inference works, and this compiles. As an exercise, I'd suggest you create an additional class:
case class RecursiveFlipped[A, F[_]](fa: F[A])
... which isn't really different from Recursive in any meaningful way, of course, but will again break type inference. Then define the additional plumbing needed to fix it. Good luck!
Edit
You asked for a less simplified version, something aware of type-classes. Some modification is required, but hopefully you can see the similarity. First, here's our upgraded Unapply:
import language.higherKinds
trait Unapply[TC[_[_]], FA] {
type F[_]
type A
def TC: TC[F]
def apply(fa: FA): F[A]
}
object Unapply {
implicit def unapply[TC[_[_]], F0[_[_], _], G0[_], A0](implicit TC0: TC[({ type λ[α] = F0[G0, α] })#λ]) =
new Unapply[TC, F0[G0, A0]] {
type F[α] = F0[G0, α]
type A = A0
def TC = TC0
def apply(fa: F0[G0, A0]): F[A] = fa
}
}
Again, this is completely ripped off from scalaz. Now some sample code using it:
import language.{ implicitConversions, higherKinds }
object Test {
// functor type class
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
// functor extension methods
object Functor {
implicit class FunctorOps[F[_], A](fa: F[A])(implicit F: Functor[F]) {
def map[B](f: A => B) = F.map(fa)(f)
}
implicit def unapply[FA](fa: FA)(implicit u: Unapply[Functor, FA]) =
new FunctorOps(u(fa))(u.TC)
}
// identity functor
case class Id[A](value: A)
object Id {
implicit val idFunctor = new Functor[Id] {
def map[A, B](fa: Id[A])(f: A => B) = Id(f(fa.value))
}
}
// pair functor
case class Pair[F[_], A](lhs: F[A], rhs: F[A])
object Pair {
implicit def pairFunctor[F[_]](implicit F: Functor[F]) = new Functor[({ type λ[α] = Pair[F, α] })#λ] {
def map[A, B](fa: Pair[F, A])(f: A => B) = Pair(F.map(fa.lhs)(f), F.map(fa.rhs)(f))
}
}
def main(args: Array[String]): Unit = {
import Functor._
val one = Id(1)
val two = Pair(one, one) map { _ + 1 }
val three = Pair(two, two) map { _ + 1 }
println(three)
}
}
Note (3 years later, July 2016), scala v2.12.0-M5 is starting to implement SI-2172 (support for higher order unification)
See commit 892a6d6 from Miles Sabin
-Xexperimental mode now only includes -Ypartial-unification
It follows Paul Chiusano's simple algorithm:
// Treat the type constructor as curried and partially applied, we treat a prefix
// as constants and solve for the suffix. For the example in the ticket, unifying
// M[A] with Int => Int this unifies as,
//
// M[t] = [t][Int => t] --> abstract on the right to match the expected arity
// A = Int --> capture the remainder on the left
The test/files/neg/t2712-1.scala includes:
package test
trait Two[A, B]
object Test {
def foo[M[_], A](m: M[A]) = ()
def test(ma: Two[Int, String]) = foo(ma) // should fail with -Ypartial-unification *disabled*
}
And (test/files/neg/t2712-2.scala):
package test
class X1
class X2
class X3
trait One[A]
trait Two[A, B]
class Foo extends Two[X1, X2] with One[X3]
object Test {
def test1[M[_], A](x: M[A]): M[A] = x
val foo = new Foo
test1(foo): One[X3] // fails with -Ypartial-unification enabled
test1(foo): Two[X1, X2] // fails without -Ypartial-unification
}

How to use implicitly with a function?

Hi I read the interesting post from Debasish about the implicitly function. I have wrote this code:
def find[C <: Business](id: String) = {
collection.findOneByID(id).map(x=> implicitly[DBObject => C].apply(x))
}
but it fails to compile with this compiler message:
could not find implicit value for parameter e: (com.mongodb.casbah.commons.Imports.DBObject) => C
what is my fault? anyone can help me?
UPDATE
My idea was this:
find is declared in a trait don't know nothing about DBObject, I don't want to put this dependency.
trait BusinessRepository {
def find[C <: Business](id: String): Option[C]
}
class MongoBusinessRepository {
val collection = ..
def find[C <: Business](id: String): Option[C] = {
collection.findOneByID(id).map(x=> implicitly[DBObject => C].apply(x))
}
implicit def DBObject2Hotel(x: DBObject): Hotel = {
// ...
// returning Hotel
}
}
case class Hotel(...) extends Business(...)
implicitly is just a convenience method to look up an implicit value that you know already exists. So it fails to compile when there is no such implicit value in scope.
A possible use case is when you use shortcut syntax for context bounds:
def find[C: Numeric](a: C, b: C): C = implicitly[Numeric[C]].plus(a, b)
Of course, in this example, the explicit form is less verbose
def find[C](a: C, b: C)(implicit n: Numeric[C]): C = n.plus(a, b)
You will find more thorough explanations in this Stackoverflow thread.
What I imagine you had in mind with your method is rather
def find[C <: Business](id: String)(implicit fun: DBObject => C) =
collection.findOneByID(id).map(fun)
I think that the problem comes from the fact that Scala compiler try to find an implicit definition of a function DBObject => C and that the only implicit definition that he can find is DBObject => Hotel that could be a solution but it's not strict. With your solution, the compiler is not able to know what should be C.
Maybe you should consider defining a DBObject2Business and so implicitly define a DBObject => Business function, or change your design to define C in a concrete class.