Recently I have found in my code several places where I was first gathering some solutions, and then continued processing them only if the solution was unique (solution collection contained only one element). Following code is an attempt to solve this in a more functional manner.
implicit class GetOnlyOne[A](val coll: Iterable[A]) {
def getonlyone = {
if (coll.isEmpty) None
else if (coll.tail.isEmpty) coll.headOption
else None
}
}
The function can be used like:
Seq(1).getonlyone
Seq(1,2).getonlyone
Set(1).getonlyone
What currently does not work is:
Some(1).getonlyone
Could the function be improved to accept Option as well, besides of Iterables, perhaps with view bounds?
You might be able to bodge something for Option with view bounds, but the general solution is to define a typeclass: you define an interface and provide an implicit instance of that interface for each type you want to support:
trait CanGetOnlyOne[F[_]] {
def getOnlyOne[A](fa: F[A]): Option[A]
}
object CanGetOnlyOne {
implicit object CanGetOnlyOneIterable extends CanGetOnlyOne[Iterable]{
def getOnlyOne[A](fa: Iterable[A]) = ...
}
implicit object CanGetOnlyOneOption extends CanGetOnlyOne[Option] {
def getOnlyOne[A](fa: Option[A]) = fa
}
}
implicit class GetOnlyOne[F[_], A](fa: F[A])(implicit cgoo: CanGetOnlyOne[F]) {
def getonlyone = cgoo.getOnlyOne(fa)
}
Option can be implicitly converted to an Iterable, so the following works:
implicit class GetOnlyOne[A, Coll](coll: Coll)
(implicit view: Coll => Iterable[A]) {
def getonlyone = {
val it: Iterable[A] = coll
if (it.isEmpty) None
else if (it.tail.isEmpty) it.headOption
else None
}
}
However for Option is this very inefficient, because your getonlyone is essentially the identity function. Therefore, I would just introduce a second method extension just for options:
implicit class GetOnlyOneOption[A](private val opt: Option[A]) extends AnyVal {
def getonlyone = opt
}
Related
Using context bounds in scala you can do stuff like
trait HasBuild[T] {
def build(buildable: T): Something
}
object Builders {
implict object IntBuilder extends HasBuild[Int] {
override def build(i: Int) = ??? // Construct a Something however appropriate
}
}
import Builders._
def foo[T: HasBuild](input: T): Something = implicitly[HasBuild[T]].build(1)
val somethingFormInt = foo(1)
Or simply
val somethingFromInt = implicitly[HasBuild[Int]].build(1)
How could I express the type of a Seq of any elements that have an appropriate implicit HasBuild object in scope? Is this possible without too much magic and external libraries?
Seq[WhatTypeGoesHere] - I should be able to find the appropriate HasBuild for each element
This obviously doesn't compile:
val buildables: Seq[_: HasBuild] = ???
Basically I'd like to be able to handle unrelated types in a common way (e.g.: build), without the user wrapping them in some kind of adapter manually - and enforce by the compiler, that the types actually can be handled. Not sure if the purpose is clear.
Something you can do:
case class HasHasBuild[A](value: A)(implicit val ev: HasBuild[A])
object HasHasBuild {
implicit def removeEvidence[A](x: HasHasBuild[A]): A = x.value
implicit def addEvidence[A: HasBuild](x: A): HasHasBuild[A] = HasHasBuild(x)
}
and now (assuming you add a HasBuild[String] for demonstration):
val buildables: Seq[HasHasBuild[_]] = Seq(1, "a")
compiles, but
val buildables1: Seq[HasHasBuild[_]] = Seq(1, "a", 1.0)
doesn't. You can use methods with implicit HasBuild parameters when you have only a HasHasBuild:
def foo1[A](x: HasHasBuild[A]) = {
import x.ev // now you have an implicit HasBuild[A] in scope
foo(x.value)
}
val somethings: Seq[Something] = buildables.map(foo1(_))
First things first, contrary to some of the comments, you are relying on context bounds. Requesting an implicit type class instance for a T is what you call a "context bound".
What you want is achievable, but not trivial and certainly not without other libraries.
import shapeless.ops.hlist.ToList
import shapeless._
import shapeless.poly_
object builder extends Poly1 {
implicit def caseGeneric[T : HasBuilder] = {
at[T](obj => implicitly[HasBuilder[T]].build(obj))
}
}
class Builder[L <: HList](mappings: L) {
def build[HL <: HList]()(
implicit fn: Mapper.Aux[builder.type, L, HL],
lister: ToList[Something]
) = lister(mappings map fn)
def and[T : HasBuilder](el: T) = new Builder[T :: L](el :: mappings)
}
object Builder {
def apply[T : HasBuilder](el: T) = new Builder(el :: HNil)
}
Now you might be able to do stuff like:
Builder(5).and("string").build()
This will call out the build methods from all the individual implcit type class instances and give you a list of the results, where every result has type Something. It relies on the fact that all the build methods have a lower upper bound of Something, e.g as per your example:
trait HasBuild[T] {
def build(buildable: T): Something
}
For some reason the following fails to work
object NtExtTest {
implicit class NaturalTransformExt[M[_], N[_]](val self: NaturalTransformation[M,N]) extends AnyVal {
def test(b:Boolean) = b
}
}
when I call the method test on a natural transform. Intellij recognises it as an extension function, but the compile gives value test is not a member of cats.~> . The same happens when using the scalaz NaturalTransformation. Is there something I can do to help the compile recognise the extension?
Scala version is 2.11.8
An example which fails:
import NtExtTest._
class NtTest[B] extends NaturalTransformation[Either[B,?], Xor[B,?]] {
def apply[A](fa: Either[B, A]): Xor[B, A] = {
fa match {
case Left(l) => Xor.left(l)
case Right(r) => Xor.right(r)
}
}
}
val test = new NtTest[String]
test.test(false)
(above uses kind projector plugin, but equally fails with type lambdas, or single param higher kinded types)
Probably relates to SI-8286
object NtExtTest {
// this will work
implicit class NatTransExt1[E](val t: NaturalTransformation[Either[E, ?], \/[E, ?]]) {
def test1(b: Boolean): Boolean = false
}
// and this will work
implicit class NatTransExt2[E](val t: NtTest[E]) {
def test2(b: Boolean): Boolean = false
}
// but this will not work, because NaturalTransformation[F, G] and
// NaturalTransformation[Either[E, ?], \/[E, ?]] of different kind
implicit class NatTransExt3[F[_], G[_]](val s: NaturalTransformation[F, G]) {
def test3(b: Boolean): Boolean = false
}
}
I.e. it is not related to NaturalTransformation. It does not work in simple case as well:
trait SomeType[F[_]]
class SomeConcreteType[A] extends SomeType[Either[A, ?]]
object SomeTypeExt {
// this will not compile
implicit class SomeTypeEnrich[F[_]](val t: SomeType[F]) {
def test1: Boolean = false
}
// this will
implicit class SomeConcreteEnrich[A](val t: SomeType[Either[A, ?]]) {
def test2: Boolean = true
}
}
If the goal to extend NtTest, probably NatTransExt1 would be best choice if one would like to stay as generic as possible. NatTransExt2 is ok, if extension really specific to NtTest.
Just when I thought I understood the basics of Scala's type system... :/
I'm trying to implement a class that reads the contents of a file and outputs a set of records. A record might be a single line, but it could also be a block of bytes, or anything. So what I'm after is a structure that allows the type of Reader to imply the type of the Record, which in turn will imply the correct Parser to use.
This structure works as long as MainApp.records(f) only returns one type of Reader. As soon as it can return more, I get this error:
could not find implicit value for parameter parser
I think the problem lies with the typed trait definitions at the top, but I cannot figure out how to fix the issue...
// Core traits
trait Record[T]
trait Reader[T] extends Iterable[Record[T]]
trait Parser[T] {
def parse(r: Record[T]): Option[Int]
}
// Concrete implementations
class LineRecord[T] extends Record[T]
class FileReader[T](f:File) extends Reader[T] {
val lines = Source.fromFile(f).getLines()
def iterator: Iterator[LineRecord[T]] =
new Iterator[LineRecord[T]] {
def next() = new LineRecord[T]
def hasNext = lines.hasNext
}
}
trait TypeA
object TypeA {
implicit object TypeAParser extends Parser[TypeA] {
def parse(r: Record[TypeA]): Option[Int] = ???
}
}
trait TypeB
object TypeB {
implicit object TypeBParser extends Parser[TypeB] {
def parse(r: Record[TypeB]): Option[Int] = ???
}
}
// The "app"
object MainApp {
def process(f: File) =
records(f) foreach { r => parse(r) }
def records(f: File) = {
if(true)
new FileReader[TypeA](f)
else
new FileReader[TypeB](f)
}
def parse[T](r: Record[T])(implicit parser: Parser[T]): Option[Int] =
parser.parse(r)
}
First off you must import the implicit object in order to use them:
import TypeA._
import TypeB._
That's not enough though. It seems like you're trying to apply implicits dynamically. That's not possible; they have to be found compile time.
If you import the objects as above and change the records so that the compiler finds the correct generic it will run fine:
def records(f: File) = new FileReader[TypeA](f)
But then it may not be what you were looking for ;)
The problem is that the return type of your records method is basically FileReader[_] (since it can return either FileReader[TypeA] or FileReader[TypeB]), and you don't provide an implicit argument of type Parser[Any]. If you remove the if-expression the return type is inferred to FileReader[TypeA], which works fine. I'm not sure what you're trying to do, but obviously the compiler can't select implicit argument based upon a type that is only known at runtime.
1) Using type with implicit inside as type parameter - doesn't bind this implicit to the host type, to do this change objects to the traits and mix them instead of generalizing (type-parametrizing):
def records(f: File) = {
if(true)
new FileReader(f) with TypeA
else
new FileReader(f) with TypeB
}
2) The parser should be in scope of function that calls parse. So you may try smthg like that:
def process(f: File) = {
val reader = records(f);
import reader._
reader foreach { r => parse(r) }
}
PlanB) Simpler alternative is to define type-parameter specific implicit methods inside the AppMain (or some trait mixed in), but it will work only if TypeA/TypeB is known on compile time, so records method can return concrete type:
implicit class TypeAParser(r: Record[TypeA]) {
def parse: Option[Int] = ???
}
implicit class TypeBParser(r: Record[TypeB]) {
def parse: Option[Int] = ???
}
def process[T <: TypeAorB](f: File) =
records[T](f).foreach(_.parse)
def recordsA[T <: TypeAorB](f: File) = new FileReader[T](f)
Here is, I think, the full set of modifications you need to do to get where I think you want to go.
import scala.io.Source
import java.io.File
import reflect.runtime.universe._
// Core traits
trait Record[+T]
trait Reader[+T] extends Iterable[Record[T]]
trait Parser[-T] {
def parse(r: Record[T]): Option[Int]
}
// Concrete implementations [unmodified]
class LineRecord[T] extends Record[T]
class FileReader[T](f:File) extends Reader[T] {
val lines = Source.fromFile(f).getLines()
def iterator: Iterator[LineRecord[T]] =
new Iterator[LineRecord[T]] {
def next() = new LineRecord[T]
def hasNext = lines.hasNext
}
}
sealed trait Alternatives
case class TypeA() extends Alternatives
object TypeA {
implicit object TypeAParser extends Parser[TypeA] {
def parse(r: Record[TypeA]): Option[Int] = ???
}
}
case class TypeB() extends Alternatives
object TypeB {
implicit object TypeBParser extends Parser[TypeB] {
def parse(r: Record[TypeB]): Option[Int] = ???
}
}
class ParseAlternator(parserA: Parser[TypeA], parserB: Parser[TypeB]) extends Parser[Alternatives] {
def parse(r: Record[Alternatives]): Option[Int] = r match {
case x: Record[TypeA #unchecked] if typeOf[Alternatives] =:= typeOf[TypeA] => parserA.parse(x)
case x: Record[TypeB #unchecked] if typeOf[Alternatives] =:= typeOf[TypeB] => parserB.parse(x)
}
}
object ParseAlternator {
implicit def parseAlternator(implicit parserA: Parser[TypeA], parserB: Parser[TypeB]): Parser[Alternatives] = new ParseAlternator(parserA, parserB)
}
// The "app"
object MainApp {
import ParseAlternator._
def process(f: File) =
records(f) foreach { r => parse(r) }
def records(f: File): Reader[Alternatives] = {
if(true)
new FileReader[TypeA](f)
else
new FileReader[TypeB](f)
}
def parse[T](r: Record[T])(implicit parser: Parser[T]): Option[Int] =
parser.parse(r)
}
The gist of it is: all of this would be completely classsical if only your parse instance did not have to pattern-match on a generic type but dealt directly with an Alternative instead.
It's this limitation (inherited from the JVM) that scala can't properly pattern-match on an object of a parametric type that requires the reflection & typeOf usage. Without it, you would just have type alternatives for your content (TypeA, TypeB), which you would add to a sealed trait, and which you would dispatch on, in an implicit that produces a Parser for their supertype.
Of course this isn't the only solution, it's just what I think is the meeting point of what's closest to what you're trying to do, with what's most idiomatic.
Ideally I'd like to be able to do the following in Scala:
import Builders._
val myBuilder = builder[TypeToBuild] // Returns instance of TypeToBuildBuilder
val obj = myBuilder.methodOnTypeToBuildBuilder(...).build()
In principle the goal is simply to be able to 'map' TypeToBuild to TypeToBuildBuilder using external mapping definitions (i.e. assume no ability to change these classes) and leverage this in type inferencing.
I got the following working with AnyRef types:
import Builders._
val myBuilder = builder(TypeToBuild)
myBuilder.methodOnTypeToBuildBuilder(...).build()
object Builders {
implicit val typeToBuildBuilderFactory =
new BuilderFactory[TypeToBuild.type, TypeToBuildBuilder]
def builder[T, B](typ: T)(implicit ev: BuilderFactory[T, B]): B = ev.create
}
class BuilderFactory[T, B: ClassTag] {
def create: B = classTag[B].runtimeClass.newInstance().asInstanceOf[B]
}
Note that the type is passed as a function argument rather than a type argument.
I'd be supremely happy just to find out how to get the above working with Any types, rather than just AnyRef types. It seems this limitation comes since Singleton types are only supported for AnyRefs (i.e. my use of TypeToBuild.type).
That being said, an answer that solves the original 'ideal' scenario (using a type argument instead of a function argument) would be fantastic!
EDIT
A possible solution that requires classOf[_] (would really love not needing to use classOf!):
import Builders._
val myBuilder = builder(classOf[TypeToBuild])
myBuilder.methodOnTypeToBuildBuilder(...).build()
object Builders {
implicit val typeToBuildBuilderFactory =
new BuilderFactory[classOf[TypeToBuild], TypeToBuildBuilder]
def builder[T, B](typ: T)(implicit ev: BuilderFactory[T, B]): B = ev.create
}
class BuilderFactory[T, B: ClassTag] {
def create: B = classTag[B].runtimeClass.newInstance().asInstanceOf[B]
}
Being able to just use builder(TypeToBuild) is really just a win in elegance/brevity. Being able to use builder[TypeToBuild] would be cool as perhaps this could one day work (with type inference advancements in Scala):
val obj: TypeToBuild = builder.methodOnTypeToBuildBuilder(...).build();
Here is a complete, working example using classOf: http://ideone.com/94rat3
Yes, Scala supports return types based on the parameters types. An example of this would be methods in the collections API like map that use the CanBuildFrom typeclass to return the desired type.
I'm not sure what you are trying to do with your example code, but maybe you want something like:
trait Builder[-A, +B] {
def create(x: A): B
}
object Builders {
implicit val int2StringBuilder = new Builder[Int, String] {
def create(x: Int) = "a" * x
}
def buildFrom[A, B](x: A)(implicit ev: Builder[A, B]): B = ev.create(x)
}
import Builders._
buildFrom(5)
The magic with newInstance only works for concrete classes that have a constructor that takes no parameters, so it probably isn't generic enough to be useful.
If you're not afraid of implicit conversions, you could do something like this:
import scala.language.implicitConversions
trait BuilderMapping[TypeToBuild, BuilderType] {
def create: BuilderType
}
case class BuilderSpec[TypeToBuild]()
def builder[TypeToBuild] = BuilderSpec[TypeToBuild]
implicit def builderSpecToBuilder[TypeToBuild, BuilderType]
(spec: BuilderSpec[TypeToBuild])
(implicit ev: BuilderMapping[TypeToBuild, BuilderType]) = ev.create
case class Foo(count: Int)
case class FooBuilder() {
def translate(f: Foo) = "a" * f.count
}
implicit val FooToFooBuilder = new BuilderMapping[Foo, FooBuilder] {
def create = FooBuilder()
}
val b = builder[Foo]
println(b.translate(Foo(3)))
The implicit conversions aren't too bad, since they're constrained to these builder-oriented types. The conversion is needed to make b.translate valid.
It looked like wingedsubmariner's answer was most of what you wanted, but you didn't want to specify both TypeToBuild and BuilderType (and you didn't necessarily want to pass a value). To achieve that, we needed to break up that single generic signature into two parts, which is why the BuilderSpec type exists.
It might also be possible to use something like partial generic application (see the answers to a question that I asked earlier), though I can't put the pieces together in my head at the moment.
I'll resort to answering my own question since a Redditor ended up giving me the answer I was looking for and they appear to have chosen not to respond here.
trait Buildable[T] {
type Result
def newBuilder: Result
}
object Buildable {
implicit object ABuildable extends Buildable[A] {
type Result = ABuilder
override def newBuilder = new ABuilder
}
implicit object BBuildable extends Buildable[B] {
type Result = BBuilder
override def newBuilder = new BBuilder
}
}
def builder[T](implicit B: Buildable[T]): B.Result = B.newBuilder
class ABuilder {
def method1() = println("Call from ABuilder")
}
class BBuilder {
def method2() = println("Call from BBuilder")
}
Then you will get:
scala> builder[A].method1()
Call from ABuilder
scala> builder[B].method2()
Call from BBuilder
You can see the reddit post here: http://www.reddit.com/r/scala/comments/2542x8/is_it_possible_to_define_a_function_return_type/
And a full working version here: http://ideone.com/oPI7Az
I have a small Scala/Neo4j application that links people and topics through "skilledAt" and "interestedIn" relations. It has a REST/Json Api (using Scalatra) and I ran into a typical type-erasure problem when I wanted to add an "asJson" method to List[Person] and List[Topic]. I would like to implement different Json serialization behaviour for the different content types but of course the types get erased. The best I've been able to come up with so far is the following runtime trick:
implicit def topicsOrPeopleAsJson[T](list: List[T]) = new {
def asJson: String = {
list match {
case head :: tail if (head.isInstanceOf[Topic]) => topicsToJson(list.asInstanceOf[List[Topic]])
case head :: tail if (head.isInstanceOf[Person]) => peopleToJson(list.asInstanceOf[List[Person]])
case _ => "[]"
}
}
private def peopleToJson(people: List[Person]) = {
...
}
private def topicsToJson(topics: List[Topic]) = {
...
}
}
This works just fine but I was wondering whether there was a better solution, maybe something including type classes, a topic I'm not very familiar with (yet).
Use another level of implicit (this is typeclasses indeed):
trait ListToJsonConverter[T] {
def asJson(l: List[T]) : String
}
implicit object PeopleToJsonConverter extends ListToJsonConverter[Person] {...}
implicit object TopicToJsonConverter extends ListToJsonConverter[Topic] {...}
implicit object DefaultJsonConverter extends ListToJsonConverter[Any] {
def asJson(l: List[Any]) = "[]"
}
implicit def topicsOrPeopleAsJson[T](list: List[T])(implicit ev : ListToJsonConverter[T]) = new {
def asJson = ev.asJson(list)
}
This may not be exactly what you asked for however. The converter will be chosen at compile time. So if you call with a list of person which the compiler knows only as a List[Any], it will not work as expected.
Why not do it the OO way?
trait JSONable {
def toJSON:String
}
class Person
class Topics
implicit def persontoJSONable(p:Person) = new PersonSerializer(p)
implicit def topicToJSONable(t:Topic) = new PersonSerializer(t)
class PersonSerializer(p:Person) extends JSONable {
override def toJSON = {
//...
}
}
class TopicSerializer(t:Topic) extends JSONable {
override def toJSON = {
//...
}
}
def ListAsJSON[T <% JSONable](l:List[T]) = {
l.map(_.toJSON)
}