Related
When I learn State Monad, I'm not sure how to compose two functions with different State return types.
State Monad definition:
case class State[S, A](runState: S => (S, A)) {
def flatMap[B](f: A => State[S, B]): State[S, B] = {
State(s => {
val (s1, a) = runState(s)
val (s2, b) = f(a).runState(s1)
(s2, b)
})
}
def map[B](f: A => B): State[S, B] = {
flatMap(a => {
State(s => (s, f(a)))
})
}
}
Two different State types:
type AppendBang[A] = State[Int, A]
type AddOne[A] = State[String, A]
Two methods with differnt State return types:
def addOne(n: Int): AddOne[Int] = State(s => (s + ".", n + 1))
def appendBang(str: String): AppendBang[String] = State(s => (s + 1, str + " !!!"))
Define a function to use the two functions above:
def myAction(n: Int) = for {
a <- addOne(n)
b <- appendBang(a.toString)
} yield (a, b)
And I hope to use it like this:
println(myAction(1))
The problem is myAction is not compilable, it reports some error like this:
Error:(14, 7) type mismatch;
found : state_monad.State[Int,(Int, String)]
required: state_monad.State[String,?]
b <- appendBang(a.toString)
^
How can I fix it? Do I have to define some Monad transformers?
Update: The question may be not clear, let me give an example
Say I want to define another function, which uses addOne and appendBang internally. Since they all need existing states, I have to pass some to it:
def myAction(n: Int)(addOneState: String, appendBangState: Int): ((String, Int), String) = {
val (addOneState2, n2) = addOne(n).runState(addOneState)
val (appendBangState2, n3) = appendBang(n2.toString).runState(appendBangState)
((addOneState2, appendBangState2), n3)
}
I have to run addOne and appendBang one by one, passing and getting the states and result manually.
Although I found it can return another State, the code is not improved much:
def myAction(n: Int): State[(String, Int), String] = State {
case (addOneState: String, appendBangState: Int) =>
val (addOneState2, n2) = addOne(n).runState(addOneState)
val (appendBangState2, n3) = appendBang(n2.toString).runState( appendBangState)
((addOneState2, appendBangState2), n3)
}
Since I'm not quite familiar with them, just wondering is there any way to improve it. The best hope is that I can use for comprehension, but not sure if that's possible
Like I mentioned in my first comment, it will be impossible to use a for comprehension to do what you want, because it can not change the type of the state (S).
Remember that a for comprehension can be translated to a combination of flatMaps, withFilter and one map. If we look at your State.flatMap, it takes a function f to change a State[S,A] into State[S, B]. We can use flatMap and map (and thus a for comprehension) to chain together operations on the same state, but we can't change the type of the state in this chain.
We could generalize your last definition of myAction to combine, compose, ... two functions using state of a different type. We can try to implement this generalized compose method directly in our State class (although this is probably so specific, it probably doesn't belong in State). If we look at State.flatMap and myAction we can see some similarities:
We first call runState on our existing State instance.
We then call runState again
In myAction we first use the result n2 to create a State[Int, String] (AppendBang[String] or State[S2, B]) using the second function (appendBang or f) on which we then call runState. But our result n2 is of type String (A) and our function appendBang needs an Int (B) so we need a function to convert A into B.
case class State[S, A](runState: S => (S, A)) {
// flatMap and map
def compose[B, S2](f: B => State[S2, B], convert: A => B) : State[(S, S2), B] =
State( ((s: S, s2: S2) => {
val (sNext, a) = runState(s)
val (s2Next, b) = f(convert(a)).runState(s2)
((sNext, s2Next), b)
}).tupled)
}
You then could define myAction as :
def myAction(i: Int) = addOne(i).compose(appendBang, _.toString)
val twoStates = myAction(1)
// State[(String, Int),String] = State(<function1>)
twoStates.runState(("", 1))
// ((String, Int), String) = ((.,2),2 !!!)
If you don't want this function in your State class you can create it as an external function :
def combineStateFunctions[S1, S2, A, B](
a: A => State[S1, A],
b: B => State[S2, B],
convert: A => B
)(input: A): State[(S1, S2), B] = State(
((s1: S1, s2: S2) => {
val (s1Next, temp) = a(input).runState(s1)
val (s2Next, result) = b(convert(temp)).runState(s2)
((s1Next, s2Next), result)
}).tupled
)
def myAction(i: Int) =
combineStateFunctions(addOne, appendBang, (_: Int).toString)(i)
Edit : Bergi's idea to create two functions to lift a State[A, X] or a State[B, X] into a State[(A, B), X].
object State {
def onFirst[A, B, X](s: State[A, X]): State[(A, B), X] = {
val runState = (a: A, b: B) => {
val (nextA, x) = s.runState(a)
((nextA, b), x)
}
State(runState.tupled)
}
def onSecond[A, B, X](s: State[B, X]): State[(A, B), X] = {
val runState = (a: A, b: B) => {
val (nextB, x) = s.runState(b)
((a, nextB), x)
}
State(runState.tupled)
}
}
This way you can use a for comprehension, since the type of the state stays the same ((A, B)).
def myAction(i: Int) = for {
x <- State.onFirst(addOne(i))
y <- State.onSecond(appendBang(x.toString))
} yield y
myAction(1).runState(("", 1))
// ((String, Int), String) = ((.,2),2 !!!)
Update (2018): my prayers were answered in Dotty (Type Lambdas), so the following Q&A is more "Scala 2.x"-related
Just a simple example from Scala:
scala> def f(x: Int) = x
f: (x: Int)Int
scala> (f _)(5)
res0: Int = 5
Let's make it generic:
scala> def f[T](x: T) = x
f: [T](x: T)T
scala> (f _)(5)
<console>:9: error: type mismatch;
found : Int(5)
required: Nothing
(f _)(5)
^
Let's look at eta-expansion of polymorphic method in Scala:
scala> f _
res2: Nothing => Nothing = <function1>
Comparison with Haskell:
Prelude> let f x = x
Prelude> f 5
5
Prelude> f "a"
"a"
Prelude> :t f
f :: t -> t
Haskell did infer correct type [T] => [T] here.
More realistic example?
scala> identity _
res2: Nothing => Nothing = <function1>
Even more realistic:
scala> def f[T](l: List[T]) = l.head
f: [T](l: List[T])T
scala> f _
res3: List[Nothing] => Nothing = <function1>
You can't make alias for identity - have to write your own function. Things like [T,U](t: T, u: U) => t -> u (make tuple) are impossible to use as values. More general - if you want to pass some lambda that rely on generic type (e.g. uses generic function, for example: creates lists, tuples, modify them in some way) - you can't do that.
So, how to solve that problem? Any workaround, solution or reasoning?
P.S. I've used term polymorphic lambda (instead of function) as function is just named lambda
Only methods can be generic on the JVM/Scala, not values. You can make an anonymous instance that implements some interface (and duplicate it for every type-arity you want to work with):
trait ~>[A[_], B[_]] { //exists in scalaz
def apply[T](a: A[T]): B[T]
}
val f = new (List ~> Id) {
def apply[T](a: List[T]) = a.head
}
Or use shapeless' Poly, which supports more complicated type-cases. But yeah, it's a limitation and it requires working around.
P∀scal is a compiler plugin that provides more concise syntax for encoding polymorphic values as objects with a generic method.
The identity function, as a value, has type ∀A. A => A. To translate that into Scala, assume a trait
trait ForAll[F[_]] {
def apply[A]: F[A]
}
Then the identity function has type ForAll[λ[A => A => A]], where I use the kind-projector syntax, or, without kind-projector:
type IdFun[A] = A => A
type PolyId = ForAll[IdFun]
And now comes the P∀scal syntactic sugar:
val id = Λ[Α](a => a) : PolyId
or equivalently
val id = ν[PolyId](a => a)
("ν" is the Greek lowercase letter "Nu", read "new")
These are really just shorthands for
new PolyId {
def apply[A] = a => a
}
Multiple type parameters and parameters of arbitrary kinds are supported by P∀scal, but you need a dedicated variation on the above ForAll trait for each variant.
I really like #Travis Brown 's solution:
import shapeless._
scala> Poly(identity _)
res2: shapeless.PolyDefns.~>[shapeless.Id,shapeless.Id] = fresh$macro$1$2$#797aa352
-
scala> def f[T](x: T) = x
f: [T](x: T)T
scala> Poly(f _)
res3: shapeless.PolyDefns.~>[shapeless.Id,shapeless.Id] = fresh$macro$2$2$#664ea816
-
scala> def f[T](l: List[T]) = l.head
f: [T](l: List[T])T
scala> val ff = Poly(f _)
ff: shapeless.PolyDefns.~>[List,shapeless.Id] = fresh$macro$3$2$#51254c50
scala> ff(List(1,2,3))
res5: shapeless.Id[Int] = 1
scala> ff(List("1","2","3"))
res6: shapeless.Id[String] = 1
Poly constructor (in some cases) will give you eta-expansion into Shapeless2 Poly1 function, which is (more-less) truly generic. However it doesn't work for multi-parameters (even with multi type-parameters), so have to "implement" Poly2 with implicit + at approach (as #som-snytt suggested), something like:
object myF extends Poly2 {
implicit def caseA[T, U] = at[T, U]{ (a, b) => a -> b}
}
scala> myF(1,2)
res15: (Int, Int) = (1,2)
scala> myF("a",2)
res16: (String, Int) = (a,2)
P.S. I would really want to see it as a part of language.
It seems to do this you will need to do a bit type hinting to help the Scala type inference system.
def id[T] : T => T = identity _
So I guess if you try to pass identity as a parameter to a function call and the types of that parameter are generic then there should be no problem.
Given two functions:
def f(a: String, b: Int): Int = a.length + b
val g: Int => String = _.toString
why is it that I can compose a partially applied f with g by means of an intermediate assignment:
val f_ = f(_: String, 42)
f_ andThen g
// String => String = <function1>
but not directly:
f(_: String, 42) andThen g
// error: value andThen is not a member of Int
Is this a problem with the type inferencer or somehow expected behavior?
This is just a syntactic error, if you turn on -Xprint:parser option you'll see the difference between your expression and the correct one, i.e: (f(_: String, 42)) andThen g.
Your expression:
((x$1: String) => f((x$1: String), 42).andThen(g))
The correct one:
((x$1: String) => f((x$1: String), 42)).andThen(g)
You can see the difference. It happens because of expansion rule, scalac first normalise syntax to the dot form and then expand it. The same rule applies to this form of function application: func(_) which is expanded to the inner-most braces, I don't remeber where in SLS it's written.
Can someone please give an example of how to use the HashMap forall() method? I find the Scala docs to be impenetrable.
What I want is something like this:
val myMap = HashMap[Int, Int](1 -> 10, 2 -> 20)
val areAllValuesTenTimesTheKey = myMap.forall((k, v) => k * 10 == v)
but this gives:
error: wrong number of parameters; expected = 1
You need instead
val myMap = HashMap[Int, Int](1 -> 10, 2 -> 20)
val areAllValuesTenTimesTheKey = myMap.forall { case (k, v) => k * 10 == v }
The problem is that forall wants a function that takes a single Tuple2, rather than two arguments. (We're thinking of a Map[A,B] as an Iterable[(A,B)] when we use forall.) Using a case statement is a nice workaround; it's really using pattern matching here to break apart the Tuple2 and give the parts names.
If you don't want to use pattern matching, you could have also written
val areAllValuesTenTimesTheKey = myMap.forall(p => p._1 * 10 == p._2 }
but I think that's less helpful.
forall is passed a single (Int, Int) Tuple (as opposed to multiple parameters). Consider this (which explicitly shows a single tuple value is decomposed):
val areAllValuesTenTimesTheKey = myMap.forall(t => t match { case (k, v) => k * 10 == v })
Or, the short-hand (which actually passes a PartialFunction):
val areAllValuesTenTimesTheKey = myMap.forall {case (k, v) => k * 10 == v}
(These both decompose the tuple take in.)
Additionally, the function can be "tupled"ed:
val myMap = Map((1,10), (2,20))
val fn = (k: Int, v: Int) => k * 10 == v
val tupled_fn = fn.tupled
val areAllValuesTenTimesTheKey = myMap.forall(tupled_fn)
myMap: scala.collection.immutable.Map[Int,Int] = Map((1,10), (2,20))
fn: (Int, Int) => Boolean = // takes in two parameters
tupled_fn: ((Int, Int)) => Boolean = // note that it now takes in a single Tuple
areAllValuesTenTimesTheKey: Boolean = true
Happy coding.
The problem with your code, is that you give forall method a function, that accepts 2 arguments and returns Boolean, or in other words (Int, Int) => Boolean. If you will look in the documentation, then you will find this signature:
def forall (p: ((A, B)) => Boolean): Boolean
in this case forall method expects Tuple2[A, B] => Boolean, so it also can be written like this:
def forall (p: Tuple2[A, B] => Boolean): Boolean
In order to fix your example you can either call forall and give it function, that accepts 1 tuple argument:
myMap.forall(keyVal => keyVal._1 * 10 == keyVal._2)
or you make patterns match and extract key and value:
myMap.forall {case (k, v) => k * 10 == v}
In this case you are giving PartialFunction[(Int, Int), Boolean] to the forall method
In Scala, the PartialFunction[A, B] class is derived from type Function[A, B] (see Scala Reference, 12.3.3). However, this seems counterintuitive to me, since a Function (which needs to be defined for all A) has more stringent requirements than a PartialFunction, which can be undefined at some places.
The problem I've come across is that when I have a partial function, I cannot use a Function to extend the partial function. Eg. I cannot do:
(pf orElse (_)=>"default")(x)
(Hope the syntax is at least remotely right)
Why is this subtyping done reversely? Are there any reasons that I've overlooked, like the fact that the Function types are built-in?
BTW, it would be also nice if Function1 :> Function0 so I needn't have the dummy argument in the example above :-)
Edit to clarify the subtyping problem
The difference between the two approaches can be emphasized by looking at two examples. Which of them is right?
One:
val zeroOne : PartialFunction[Float, Float] = { case 0 => 1 }
val sinc = zeroOne orElse ((x) => sin(x)/x) // should this be a breach of promise?
Two:
def foo(f : (Int)=>Int) {
print(f(1))
}
val bar = new PartialFunction[Int, Int] {
def apply(x : Int) = x/2
def isDefinedAt(x : Int) = x%2 == 0
}
foo(bar) // should this be a breach of promise?
Because in Scala (as in any Turing complete language) there is no guarantee that a Function is total.
val f = {x : Int => 1 / x}
That function is not defined at 0. A PartialFunction is just a Function that promises to tell you where it's not defined. Still, Scala makes it easy enough to do what you want
def func2Partial[A,R](f : A => R) : PartialFunction[A,R] = {case x => f(x)}
val pf : PartialFunction[Int, String] = {case 1 => "one"}
val g = pf orElse func2Partial{_ : Int => "default"}
scala> g(1)
res0: String = one
scala> g(2)
res1: String = default
If you prefer, you can make func2Partial implicit.
PartialFunction has methods which Function1 does not, therefore it is the subtype. Those methods are isDefinedAt and orElse.
Your real problem is that PartialFunctions are not inferred sometimes when you'd really like them to be. I'm hopeful that will be addressed at some future date. For instance this doesn't work:
scala> val pf: PartialFunction[String, String] = { case "a" => "foo" }
pf: PartialFunction[String,String] = <function>
scala> pf orElse { case x => "default" }
<console>:6: error: missing parameter type for expanded function
((x0$1) => x0$1 match { case (x # _) => "default" })
But this does:
scala> pf orElse ({ case x => "default" } : PartialFunction[String,String])
res5: PartialFunction[String,String] = <function>
Of course you could always do this:
scala> implicit def f2pf[T,R](f: Function1[T,R]): PartialFunction[T,R] =
new PartialFunction[T,R] {
def apply(x: T) = f(x)
def isDefinedAt(x: T) = true
}
f2pf: [T,R](f: (T) => R)PartialFunction[T,R]
And now it's more like you want:
scala> pf orElse ((x: String) => "default")
res7: PartialFunction[String,String] = <function>
scala> println(res7("a") + " " + res7("quux"))
foo default