Is there any way to create a PartialFunction except through the case statement?
I'm curious, because I'd like to express the following (scala pseudo ahead!)...
val bi = BigInt(_)
if (bi.isValidInt) bi.intValue
... as a partial function, and doing
val toInt : PartialFunction[String, Int] = {
case s if BigInt(s).isValidInt => BigInt(s).intValue
}
seems redundant since I create a BigInt twice.
Not sure I understand the question. But here's my attempt: Why not create an extractor?
object ValidBigInt {
def unapply(s: String): Option[Int] = {
val bi = BigInt(s)
if (bi.isValidInt) Some(bi.intValue) else None
}
}
val toInt: PartialFunction[String, Int] = {
case ValidBigInt(i) => i
}
The other option is (and that may answer the question as to whether one can create PartialFunction other than with a case literal):
val toInt = new PartialFunction[String, Int] {
def isDefinedAt(s: String) = BigInt(s).isValidInt
def apply(s: String) = BigInt(s).intValue
}
However since the idea of a partial function is that it's only partially defined, in the end you will still do redundant things -- you need to create a big int to test whether it's valid, and then in the function application you create the big int again...
I saw a project at Github that tried to come around this by somewhat caching the results from isDefinedAt. If you go down to the benchmarks, you'll see that it turned out to be slower than the default Scala implementation :)
So if you want to get around the double nature of isDefinedAt versus apply, you should just go straight for a (full) function that provides an Option[Int] as result.
I think you're looking for lift/unlift. lift takes a partial function and turns it into a function that returns an Option. Unlift takes a function with one argument that returns an option, and returns a partial function.
import scala.util.control.Exception._
scala> def fn(s: String) = catching(classOf[NumberFormatException]) opt {BigInt(s)}
fn: (s: String)Option[scala.math.BigInt]
scala> val fnPf = Function.unlift(fn)
fnPf: PartialFunction[String,scala.math.BigInt] = <function1>
scala> val fn = fnPf.lift
fn: String => Option[scala.math.BigInt] = <function1>
Closely related, you also want to look at this answer for information about cond and condOpt:
scala> import PartialFunction._
import PartialFunction._
scala> cond("abc") { case "def" => true }
res0: Boolean = false
scala> condOpt("abc") { case x if x.length == 3 => x + x }
res1: Option[java.lang.String] = Some(abcabc)
You can write out a PartialFunction "longhand" if you'd like:
object pf extends PartialFunction[Int,String] {
def isDefinedAt(in: Int) = in % 2 == 0
def apply(in: Int) = {
if (in % 2 == 0)
"even"
else
throw new MatchError(in + " is odd")
}
Okay, I got this
import java.lang.NumberFormatException
import scala.util.control.Exception._
val toInt: PartialFunction[String, Int] = {
catching(classOf[NumberFormatException]) opt BigInt(_) match {
case Some(bi) if bi.isValidInt => bi.intValue
}
}
How about this?
val toInt: PartialFunction[String, Int] = (s: String) => BigInt(s) match {
case bi if bi.isValidInt => bi.intValue
}
Related
I am currently reading Hutton's and Meijer's paper on parsing combinators in Haskell http://www.cs.nott.ac.uk/~pszgmh/monparsing.pdf. For the sake of it I am trying to implement them in scala. I would like to construct something easy to code, extend and also simple and elegant. I have come up with two solutions for the following haskell code
/* Haskell Code */
type Parser a = String -> [(a,String)]
result :: a -> Parser a
result v = \inp -> [(v,inp)]
zero :: Parser a
zero = \inp -> []
item :: Parser Char
item = \inp -> case inp of
[] -> []
(x:xs) -> [(x,xs)]
/* Scala Code */
object Hutton1 {
type Parser[A] = String => List[(A, String)]
def Result[A](v: A): Parser[A] = str => List((v, str))
def Zero[A]: Parser[A] = str => List()
def Character: Parser[Char] = str => if (str.isEmpty) List() else List((str.head, str.tail))
}
object Hutton2 {
trait Parser[A] extends (String => List[(A, String)])
case class Result[A](v: A) extends Parser[A] {
def apply(str: String) = List((v, str))
}
case object Zero extends Parser[T forSome {type T}] {
def apply(str: String) = List()
}
case object Character extends Parser[Char] {
def apply(str: String) = if (str.isEmpty) List() else List((str.head, str.tail))
}
}
object Hutton extends App {
object T1 {
import Hutton1._
def run = {
val r: List[(Int, String)] = Zero("test") ++ Result(5)("test")
println(r.map(x => x._1 + 1) == List(6))
println(Character("abc") == List(('a', "bc")))
}
}
object T2 {
import Hutton2._
def run = {
val r: List[(Int, String)] = Zero("test") ++ Result(5)("test")
println(r.map(x => x._1 + 1) == List(6))
println(Character("abc") == List(('a', "bc")))
}
}
T1.run
T2.run
}
Question 1
In Haskell, zero is a function value that can be used as it is, expessing all failed parsers whether they are of type Parser[Int] or Parser[String]. In scala we achieve the same by calling the function Zero (1st approach) but in this way I believe that I just generate a different function everytime Zero is called. Is this statement true? Is there a way to mitigate this?
Question 2
In the second approach, the Zero case object is extending Parser with the usage of existential types Parser[T forSome {type T}] . If I replace the type with Parser[_] I get the compile error
Error:(19, 28) class type required but Hutton2.Parser[_] found
case object Zero extends Parser[_] {
^
I thought these two expressions where equivalent. Is this the case?
Question 3
Which approach out of the two do you think that will yield better results in expressing the combinators in terms of elegance and simplicity?
I use scala 2.11.8
Note: I didn't compile it, but I know the problem and can propose two solutions.
The more Haskellish way would be to not use subtyping, but to define zero as a polymorphic value. In that style, I would propose to define parsers not as objects deriving from a function type, but as values of one case class:
final case class Parser[T](run: String => List[(T, String)])
def zero[T]: Parser[T] = Parser(...)
As shown by #Alec, yes, this will produce a new value every time, since a def is compiled to a method.
If you want to use subtyping, you need to make Parser covariant. Then you can give zero a bottom result type:
trait Parser[+A] extends (String => List[(A, String)])
case object Zero extends Parser[Nothing] {...}
These are in some way quite related; in system F_<:, which is the base of what Scala uses, the types _|_ (aka Nothing) and \/T <: Any. T behave the same (this hinted at in Types and Programming Languages, chapter 28). The two possibilities given here are a consequence of this fact.
With existentials I'm not so familiar with, but I think that while unbounded T forSome {type T} will behave like Nothing, Scala does not allow inhertance from an existential type.
Question 1
I think that you are right, and here is why: Zero1 below prints hello every time you use it. The solution, Zero2, involves using a val instead.
def Zero1[A]: Parser[A] = { println("hi"); str => List() }
val Zero2: Parser[Nothing] = str => List()
Question 2
No idea. I'm still just starting out with Scala. Hope someone answers this.
Question 3
The trait one will play better with Scala's for (since you can define custom flatMap and map), which turns out to be (somewhat) like Haskell's do. The following is all you need.
trait Parser[A] extends (String => List[(A, String)]) {
def flatMap[B](f: A => Parser[B]): Parser[B] = {
val p1 = this
new Parser[B] {
def apply(s1: String) = for {
(a,s2) <- p1(s1)
p2 = f(a)
(b,s3) <- p2(s2)
} yield (b,s3)
}
}
def map[B](f: A => B): Parser[B] = {
val p = this
new Parser[B] {
def apply(s1: String) = for ((a,s2) <- p(s1)) yield (f(a),s2)
}
}
}
Of course, to do anything interesting you need more parsers. I'll propose to you one simple parser combinator: Choice(p1: Parser[A], p2: Parser[A]): Parser[A] which tries both parsers. (And rewrite your existing parsers more to my style).
def choice[A](p1: Parser[A], p2: Parser[A]): Parser[A] = new Parser[A] {
def apply(s: String): List[(A,String)] = { p1(s) ++ p2(s) }
}
def unit[A](x: A): Parser[A] = new Parser[A] {
def apply(s: String): List[(A,String)] = List((x,s))
}
val character: Parser[Char] = new Parser[Char] {
def apply(s: String): List[(Char,String)] = List((s.head,s.tail))
}
Then, you can write something like the following:
val parser: Parser[(Char,Char)] = for {
x <- choice(unit('x'),char)
y <- char
} yield (x,y)
And calling parser("xyz") gives you List((('x','x'),"yz"), (('x','y'),"z")).
I have a generic map with values, some of which can be in turn lists of values.
I'm trying to process a given key and convert the results to the type expected by an outside caller, like this:
// A map with some values being other collections.
val map: Map[String, Any] = Map("foo" -> 1, "bar" -> Seq('a', 'b'. 'a'))
// A generic method with a "specialization" for collections (pseudocode)
def cast[T](key: String) = map.get(key).map(_.asInstanceOf[T])
def cast[C <: Iterable[T]](key: String) = map.get(key).map(list => list.to[C].map(_.asIntanceOf[T]))
// Expected usage
cast[Int]("foo") // Should return 1:Int
cast[Set[Char]]("bar") // Should return Set[Char]('a', 'b')
This is to show what I would like to do, but it does not work. The compiler error complains (correctly, about 2 possible matches). I've also tried to make this a single function with some sort of pattern match on the type to no avail.
I've been reading on #specialized, TypeTag, CanBuildFrom and other scala functionality, but I failed to find a simple way to put it all together. Separate examples I've found address different pieces and some ugly workarounds, but nothing that would simply allow an external user to call cast and get an exception is the cast was invalid. Some stuff is also old, I'm using Scala 2.10.5.
This appears to work but it has a some problems.
def cast[T](m: Map[String, Any], k: String):T = m(k) match {
case x: T => x
}
With the right input you get the correct output.
scala> cast[Int](map,"foo")
res18: Int = 1
scala> cast[Set[Char]](map,"bar")
res19: Set[Char] = Set(a, b)
But it throws if the type is wrong for the key or if the map has no such key (of course).
You can do this via implicit parameters:
val map: Map[String, Any] = Map("foo" -> 1, "bar" -> Set('a', 'b'))
abstract class Casts[B] {def cast(a: Any): B}
implicit val doubleCast = new Casts[Double] {
override def cast(a: Any): Double = a match {
case x: Int => x.toDouble
}
}
implicit val intCast = new Casts[Int] {
override def cast(a: Any): Int = a match {
case x: Int => x
case x: Double => x.toInt
}
}
implicit val seqCharCast = new Casts[Seq[Char]] {
override def cast(a: Any): Seq[Char] = a match {
case x: Set[Char] => x.toSeq
case x: Seq[Char] => x
}
}
def cast[T](key: String)(implicit p:Casts[T]) = p.cast(map(key))
println(cast[Double]("foo")) // <- 1.0
println(cast[Int]("foo")) // <- 1
println(cast[Seq[Char]]("bar")) // <- ArrayBuffer(a, b) which is Seq(a, b)
But you still need to iterate over all type-to-type options, which is reasonable as Set('a', 'b').asInstanceOf[Seq[Char]] throws, and you cannot use a universal cast, so you need to handle such cases differently.
Still it sounds like an overkill, and you may need to review your approach from global perspective
Is that possible to somehow marshall PartialFunction (let's assume it will always contains only one case) into something human-readable?
Let's say we have collection of type Any (messages: List[Any])
and number of PartialFuntion[Any, T] defined using pattern matching block.
case object R1
case object R2
case object R3
val pm1: PartialFunction[Any, Any] = {
case "foo" => R1
}
val pm2: PartialFunction[Any, Any] = {
case x: Int if x > 10 => R2
}
val pm3: PartialFunction[Any, Any] = {
case x: Boolean => R3
}
val messages: List[Any] = List("foo", 20)
val functions = List(pm1, pm2)
then we can find all the messages matched by provided PFs and related applications
val found: List[Option[Any]] = functions map { f =>
messages.find(f.isDefined).map(f)
}
but what if I need resulting map of 'what I expect' to 'what I've got' in the human-readable form (for logging). Say,
(case "foo") -> Some(R1)
(case Int if _ > 10) -> Some(R2)
(case Boolean) -> None
Is that possible? Some macro/meta works?
There's nothing at runtime which will print compiled code nicely.
You could write a macro which will print the source code of the tree and use that? Most macro tutorials start with a macro for printing source code -- see e.g. http://www.warski.org/blog/2012/12/starting-with-scala-macros-a-short-tutorial/
Perhaps:
// Given a partial function "pf", return the source code for pf
// as a string as well as the compiled, runnable function itself
def functionAndSource(pf: PartialFunction[Any, Any]): (String, PartialFunction[Any, Any]) = macro functionAndSourceImpl
def functionAndSourceImpl ...
val pm1: (String, PartialFunction[Any, Any]) = functionAndSource {
case "foo" => R1
}
This isn't ever going to be that easy or nice in Scala.
Scala isn't Lisp or Ruby: it's a compiled language and it is not optimised for reflection on the code itself.
Thanks for your answers. Using Macro is interesting one choice.
But as an option the solution might be to use kind of named partial functions. The idea is to name the function so in the output you can see the name of function instead source code.
object PartialFunctions {
type FN[Result] = PartialFunction[Any, Result]
case class NamedPartialFunction[A,B](name: String)(pf: PartialFunction[A, B]) extends PartialFunction[A,B] {
override def isDefinedAt(x: A): Boolean = pf.isDefinedAt(x)
override def apply(x: A): B = pf.apply(x)
override def toString(): String = s"matching($name)"
}
implicit class Named(val name: String) extends AnyVal {
def %[A,B](pf: PartialFunction[A,B]) = new NamedPartialFunction[A, B](name)(pf)
}
}
So then you can use it as follows
import PartialFunctions._
val pm1: PartialFunction[Any, Any] = "\"foo\"" % {
case "foo" => R1
}
val pm2: PartialFunction[Any, Any] = "_: Int > 10" % {
case x: Int if x > 10 => R2
}
val pm3: PartialFunction[Any, Any] = "_: Boolean" % {
case x: Boolean => R3
}
val messages: List[Any] = List("foo", 20)
val functions = List(pm1, pm2)
val found: List[Option[(String, Any)]] = functions map { case f: NamedPartialFunction =>
messages.find(f.isDefined).map(m => (f.name, f(m))
}
I'm doing a bit of Scala gymnastics where I have Seq[T] in which I try to find the "smallest" element. This is what I do right now:
val leastOrNone = seq.reduceOption { (best, current) =>
if (current.something < best.something) current
else best
}
It works fine, but I'm not quite satisfied - it's a bit long for such a simple thing, and I don't care much for "if"s. Using minBy would be much more elegant:
val least = seq.minBy(_.something)
... but min and minBy throw exceptions when the sequence is empty. Is there an idiomatic, more elegant way of finding the smallest element of a possibly empty list as an Option?
seq.reduceOption(_ min _)
does what you want?
Edit: Here's an example incorporating your _.something:
case class Foo(a: Int, b: Int)
val seq = Seq(Foo(1,1),Foo(2,0),Foo(0,3))
val ord = Ordering.by((_: Foo).b)
seq.reduceOption(ord.min) //Option[Foo] = Some(Foo(2,0))
or, as generic method:
def minOptionBy[A, B: Ordering](seq: Seq[A])(f: A => B) =
seq reduceOption Ordering.by(f).min
which you could invoke with minOptionBy(seq)(_.something)
Starting Scala 2.13, minByOption/maxByOption is now part of the standard library and returns None if the sequence is empty:
seq.minByOption(_.something)
List((3, 'a'), (1, 'b'), (5, 'c')).minByOption(_._1) // Option[(Int, Char)] = Some((1,b))
List[(Int, Char)]().minByOption(_._1) // Option[(Int, Char)] = None
A safe, compact and O(n) version with Scalaz:
xs.nonEmpty option xs.minBy(_.foo)
Hardly an option for any larger list due to O(nlogn) complexity:
seq.sortBy(_.something).headOption
Also, it is available to do like that
Some(seq).filter(_.nonEmpty).map(_.minBy(_.something))
How about this?
import util.control.Exception._
allCatch opt seq.minBy(_.something)
Or, more verbose, if you don't want to swallow other exceptions:
catching(classOf[UnsupportedOperationException]) opt seq.minBy(_.something)
Alternatively, you can pimp all collections with something like this:
import collection._
class TraversableOnceExt[CC, A](coll: CC, asTraversable: CC => TraversableOnce[A]) {
def minOption(implicit cmp: Ordering[A]): Option[A] = {
val trav = asTraversable(coll)
if (trav.isEmpty) None
else Some(trav.min)
}
def minOptionBy[B](f: A => B)(implicit cmp: Ordering[B]): Option[A] = {
val trav = asTraversable(coll)
if (trav.isEmpty) None
else Some(trav.minBy(f))
}
}
implicit def extendTraversable[A, C[A] <: TraversableOnce[A]](coll: C[A]): TraversableOnceExt[C[A], A] =
new TraversableOnceExt[C[A], A](coll, identity)
implicit def extendStringTraversable(string: String): TraversableOnceExt[String, Char] =
new TraversableOnceExt[String, Char](string, implicitly)
implicit def extendArrayTraversable[A](array: Array[A]): TraversableOnceExt[Array[A], A] =
new TraversableOnceExt[Array[A], A](array, implicitly)
And then just write seq.minOptionBy(_.something).
I have the same problem before, so I extends Ordered and implement the compare function.
here is example:
case class Point(longitude0: String, latitude0: String) extends Ordered [Point]{
def this(point: Point) = this(point.original_longitude,point.original_latitude)
val original_longitude = longitude0
val original_latitude = latitude0
val longitude = parseDouble(longitude0).get
val latitude = parseDouble(latitude0).get
override def toString: String = "longitude: " +original_longitude +", latitude: "+ original_latitude
def parseDouble(s: String): Option[Double] = try { Some(s.toDouble) } catch { case _ => None }
def distance(other: Point): Double =
sqrt(pow(longitude - other.longitude, 2) + pow(latitude - other.latitude, 2))
override def compare(that: Point): Int = {
if (longitude < that.longitude)
return -1
else if (longitude == that.longitude && latitude < that.latitude)
return -1
else
return 1
}
}
so if I have a seq of Point
I can ask for max or min method
var points = Seq[Point]()
val maxPoint = points.max
val minPoint = points.min
You could always do something like:
case class Foo(num: Int)
val foos: Seq[Foo] = Seq(Foo(1), Foo(2), Foo(3))
val noFoos: Seq[Foo] = Seq.empty
def minByOpt(foos: Seq[Foo]): Option[Foo] =
foos.foldLeft(None: Option[Foo]) { (acc, elem) =>
Option((elem +: acc.toSeq).minBy(_.num))
}
Then use like:
scala> minByOpt(foos)
res0: Option[Foo] = Some(Foo(1))
scala> minByOpt(noFoos)
res1: Option[Foo] = None
For scala < 2.13
Try(seq.minBy(_.something)).toOption
For scala 2.13
seq.minByOption(_.something)
In Haskell you'd wrap the minimumBy call as
least f x | Seq.null x = Nothing
| otherwise = Just (Seq.minimumBy f x)
Suppose that I have a string in scala and I want to try to parse a double out of it.
I know that, I can just call toDouble and then catch the java num format exception if this fails, but is there a cleaner way to do this? For example if there was a parseDouble function that returned Option[Double] this would qualify.
I don't want to put this in my own code if it already exists in the standard library and I am just looking for it in the wrong place.
Thanks for any help you can provide.
For Scala 2.13+ see Xavier's answer below. Apparently there's a toDoubleOption method now.
For older versions:
def parseDouble(s: String) = try { Some(s.toDouble) } catch { case _ => None }
Fancy version (edit: don't do this except for amusement value; I was a callow youth years ago when I used to write such monstrosities):
case class ParseOp[T](op: String => T)
implicit val popDouble = ParseOp[Double](_.toDouble)
implicit val popInt = ParseOp[Int](_.toInt)
// etc.
def parse[T: ParseOp](s: String) = try { Some(implicitly[ParseOp[T]].op(s)) }
catch {case _ => None}
scala> parse[Double]("1.23")
res13: Option[Double] = Some(1.23)
scala> parse[Int]("1.23")
res14: Option[Int] = None
scala> parse[Int]("1")
res15: Option[Int] = Some(1)
Scalaz provides an extension method parseDouble on Strings, which gives a value of type Validation[NumberFormatException, Double].
scala> "34.5".parseDouble
res34: scalaz.Validation[NumberFormatException,Double] = Success(34.5)
scala> "34.bad".parseDouble
res35: scalaz.Validation[NumberFormatException,Double] = Failure(java.lang.NumberFormatException: For input string: "34.bad")
You can convert it to Option if so required.
scala> "34.bad".parseDouble.toOption
res36: Option[Double] = None
scala> import scala.util.Try
import scala.util.Try
scala> def parseDouble(s: String): Option[Double] = Try { s.toDouble }.toOption
parseDouble: (s: String)Option[Double]
scala> parseDouble("3.14")
res0: Option[Double] = Some(3.14)
scala> parseDouble("hello")
res1: Option[Double] = None
Scala 2.13 introduced String::toDoubleOption:
"5.7".toDoubleOption // Option[Double] = Some(5.7)
"abc".toDoubleOption // Option[Double] = None
"abc".toDoubleOption.getOrElse(-1d) // Double = -1.0
You could try using util.control.Exception.catching which returns an Either type.
So using the following returns a Left wrapping a NumberFormatException or a Right wrapping a Double
import util.control.Exception._
catching(classOf[NumberFormatException]) either "12.W3".toDouble
Unfortunately, this isn't in the standard library. Here's what I use:
class SafeParsePrimitive(s: String) {
private def nfe[T](t: => T) = {
try { Some(t) }
catch { case nfe: NumberFormatException => None }
}
def booleanOption = s.toLowerCase match {
case "yes" | "true" => Some(true)
case "no" | "false" => Some(false)
case _ => None
}
def byteOption = nfe(s.toByte)
def doubleOption = nfe(s.toDouble)
def floatOption = nfe(s.toFloat)
def hexOption = nfe(java.lang.Integer.valueOf(s,16))
def hexLongOption = nfe(java.lang.Long.valueOf(s,16))
def intOption = nfe(s.toInt)
def longOption = nfe(s.toLong)
def shortOption = nfe(s.toShort)
}
implicit def string_parses_safely(s: String) = new SafeParsePrimitive(s)
There's nothing like this not only in Scala, but even in basic Java.
Here's a piece code that does it without exceptions, though:
def parseDouble(s: String)(implicit nf: NumberFormat) = {
val pp = new ParsePosition(0)
val d = nf.parse(s, pp)
if (pp.getErrorIndex == -1) Some(d.doubleValue) else None
}
Usage:
implicit val formatter = NumberFormat.getInstance(Locale.ENGLISH)
Console println parseDouble("184.33")
Console println parseDouble("hello, world")
I'd usually go with an "in place" Try:
def strTimesTen (s: String) = for (d <- Try(s.toDouble)) yield d * 10
strTimesTen("0.1") match {
Success(d) => println( s"It is $d" )
Failure(ex) => println( "I've asked for a number!" )
}
Note, that you can do further calculation in the for and any exception would project into a Failure(ex). AFAIK this is the idiomatic way of handling a sequence of unreliable operations.