Scalaz Writer Monad and filterM - scala

I am working my way through learning scalaz and Learn You A Haskell For Greater Good and wonder how to translate the filterM example from LYAHFGG to Scala.
fst $ runWriter $ filterM keepSmall [9,1,5,2,10,3]
with keepSmall defined as
keepSmall :: Int -> Writer [String] Bool
keepSmall x
| x < 4 = do
tell ["Keeping " ++ show x]
return True
| otherwise = do
tell [show x ++ " is too large, throwing it away"]
return False
My naive approach ends with compilation errors and I have no clue how to go around that issue!
val keepSmall: (Int => WriterT[Id, Vector[String], Boolean]) = (x: Int) =>
if (x < 4) for {
_ <- Vector("Keeping " + x.shows).tell
} yield true
else for {
_ <- Vector(x.shows + " is too large, throwing it away").tell
} yield false
println(List(9,1,5,2,10,3) filterM keepSmall)
Compilation errors:
Error:(182, 32) no type parameters for method filterM: (p: Int => M[Boolean])(implicit evidence$4: scalaz.Applicative[M])M[List[Int]] exist so that it can be applied to arguments (Int => scalaz.WriterT[scalaz.Scalaz.Id,Vector[String],Boolean])
--- because ---
argument expression's type is not compatible with formal parameter type;
found : Int => scalaz.WriterT[scalaz.Scalaz.Id,Vector[String],Boolean]
required: Int => ?M[Boolean]
println(List(9,1,5,2,10,3) filterM keepSmall)
^
and
Error:(182, 40) type mismatch;
found : Int => scalaz.WriterT[scalaz.Scalaz.Id,Vector[String],Boolean]
required: Int => M[Boolean]
println(List(9,1,5,2,10,3) filterM keepSmall)
^

The issue is due to the fact that Scala can't really know how to fit a type with three holes into the argument expected by filterM, which has only one hole filled with a Boolean.
You could solve your problem using some weird type-lambda syntax like this (not tested, may not work):
val keepSmall: (Int => ({type L[T] = WriterT[Id, Vector[String], T]})#L) = ...
Or (much easier) by introducing a type alias as follows:
type MyWriter[T] = WriterT[Id, Vector[String], T]
val keepSmall: (Int => MyWriter[Boolean]) = ...
This will make sure that the kind of the argument expected by filterM matches with the kind of the argument you are providing.

Related

Odd Scala ClassCastException

The following code compiles, but throws an exception on the last line. Why is this? How can I avoid it? (The code below is contrived to show the problem; I do need to do something similar in actual code.)
type F = Int => Int
val f: Int => Int = identity
val g1: F => F = identity
val g2: F => F = (identity _).asInstanceOf[F => F]
println("f = " + f)
println("g1 = " + g1)
println("g2 = " + g2)
val h1: Int => Int = g1(f: Int => Int)
val h2: Int => Int = g2(f: Int => Int)
Here is the output of the code:
f = doodle.Bug$$$Lambda$7/1836797772#4b53f538
g1 = doodle.Bug$$$Lambda$8/1383547042#543e710e
g2 = doodle.Bug$$$Lambda$9/3213500#57f23557
Here is the exception:
java.lang.ClassCastException: doodle.Bug$$$Lambda$7/1836797772 cannot be cast to scala.runtime.Nothing$
I find it particularly strange that casting g2 results in an implicit cast on f...
Wild guess: ammonite suggest that this:
(identity _)
has a type of:
Nothing => Nothing
Scala might remember this fact. Maybe because of specialization or (more likely) maybe Eta expansion of identity creates a closure that remember that it IS Nothing => Nothing function that underneath call identity.
In such situation, when you use it in context where JVM does an actual check (so not at the moment you run asInstanceOf, but during the application), then casting fails and you see the exception.
identity[F] _
works as expected without exception.

Scala function composition: brackets and types

(1) Having defined two functions in the Scala REPL:
scala> def f(s: String) = "f(" + s + ")"
f: (s: String)String
scala> def g(s: String) = "g(" + s + ")"
g: (s: String)String
(2) Composing them without brackets works as expected:
scala> f _ compose g _
res18: String => String = <function1>
(3) Composing them with brackets doesn't:
scala> f(_).compose(g(_))
<console>:14: error: missing parameter type for expanded function ((x$1) => f(x$1).compose(((x$2) => g(x$2))))
f(_).compose(g(_))
^
<console>:14: error: missing parameter type for expanded function ((x$2) => g(x$2))
f(_).compose(g(_))
^
<console>:14: error: type mismatch;
found : String
required: Int
f(_).compose(g(_))
^
Question 1: Can somebody explain why?
Question 2: Why the type mismatch? Why is Scala expecting an Int at all?
(4) Surrounding f(_) with brackets seems to help a little bit, by making the first two errors go away:
scala> (f(_)).compose(g(_))
<console>:14: error: missing parameter type for expanded function ((x$2) => g(x$2))
(f(_)).compose(g(_))
^
Question 3: Why do these brackets help?
Question 4: Why does Scala need the parameter types, even though they are clearly defined in f and g respectively?
(5) Finally, adding the parameter type makes it work:
scala> (f(_)).compose(g(_:String))
res22: String => String = <function1>
Could you please explain what's going on, and provide alternative syntaxes to achieve the composition?
Thanks.
You can see the (unexpected) expansion using magic show comment:
scala> f(_).compose(g(_)) // show
[snip]
val res0 = ((x$1) => f(x$1).compose(((x$2) => g(x$2))))
Function literals need the params constrained, as you showed. f _ is eta expansion, which is different from f(_) which is sugar for x => f(x).
Since the unintended application f(x$1) returns a string, which is a Int => Char for indexing, you get the added type mismatch.
Underscore is covered by many SO questions, including one canonical.

Odd issue with generic function in Scala

I'm in the process of learning a bit about Scala in order to see how it compares to F#, which is what I spend most of my time with. I'm attempting a pretty straightforward memoization technique for functions. In F# I would use something like this:
open System.Collections.Generic
let memoize (f : 'a -> 'b) =
// A dictionary in which to cache results of previous
// calls of the function
let dict = new Dictionary<'a, 'b>()
let memoizedFunction input =
match dict.TryGetValue(input) with
| true, x -> x
| false, _ ->
let answer = f input
dict.Add(input, answer)
answer
memoizedFunction
In attempting to produce an equivalent version of this in Scala I've come up with the following:
def memoize[A, B](f: A => B): A => B = {
val dict = collection.mutable.WeakHashMap[A, B]()
def memoizedFunction[A, B](input: A): B =
dict.get(input) match {
case x: Some[B] => x
case _ =>
val answer = f(input)
dict += ((input, answer))
answer
}
memoizedFunction _
}
I'm receiving a few errors in the REPL when I attempt to define this function:
<console>:11: error: type mismatch;
found : input.type (with underlying type A)
required: A
dict.get(input) match {
^
<console>:14: error: type mismatch;
found : input.type (with underlying type A)
required: A
val answer = f(input)
^
<console>:15: error: type mismatch;
found : input.type (with underlying type A)
required: A
dict += ((input, answer))
^
Can anyone point out where I'm going wrong here?
The type parameters on memoizedFunction shadow the outer type parameters. The nitty-gritty of Scala generics escapes me, but that's why input's type of A isn't the A that Scala is looking for.
Also, x: Some[B] conflicts with the return type of memoizedFunction, which is B. The idiomatic way to match Option is Some(x) => // do something with x.
So here's what I've got with those 2 things corrected:
def memoize[A, B](f: A => B): A => B = {
val dict = collection.mutable.WeakHashMap[A, B]()
def memoizedFunction(input: A): B =
dict.get(input) match {
case Some(x) => x
case _ =>
val answer = f(input)
dict += ((input, answer))
answer
}
memoizedFunction _
}

Type bounds on functions

I am having trouble getting my code with parameterized types to pass the scala compiler. My goal is to be able to express (Predicate, Action) pairs as shown in the MyProg object.
trait ProgBase {
type Predicate[T] = T => Boolean
type Action[T] = T => Unit
private var prog = List[(Predicate[Any], Action[Any])]()
final def on[T <: Any](pred: Predicate[T])(action: Action[T]) = {
prog = (pred, action) :: prog // gives type mismatch
}
// remainder of trait elided
}
object MyProg extends ProgBase {
on[String](s => !s.isEmpty) { s =>
println(s + " is not empty")
}
on[Int](i => i.isValidByte) { i =>
println(i + " can fit in a byte")
}
}
By specifying that T has an upper bound of Any, I hoped this would appease the compiler, but clearly I am missing something:
[error] ......ProgBase.scala:8 type mismatch;
[error] found : (T => Boolean, T => Unit)
[error] required: (Any => Boolean, Any => Unit)
[error] prog = (pred, action) :: prog
[error] ^
First of all, answer to your question, if you write:
private var prog = List[(Predicate[_ <: Any], Action[_ <: Any])]()
It all compiles OK. We should use wildcards, 'cause the type of elements are unknown.
Second, maybe you mistyped, you can't use your on function as you used it, use it something like:
on[String](s => !s.isEmpty)(s => !s.isEmpty)
It caused by type mismatch: type Action[T] = T => Unit but println has type Unit,
so as a variant u can simply write: type Action = Unit. Obviously, u can avoid using this type alias at all.
Third, maybe you already know, and I shoudn't tell you, that in fact, you lose all information about predicate types - let's check it using Scala reflection:
import scala.reflect.runtime.{universe => ru}
def getTypeTag[T: ru.TypeTag](obj: T) = ru.typeTag[T]
val s: String = "123"
val i: Int = 123
on[String](s => !s.isEmpty)(s => !s.isEmpty)
on[Int](i => i.isValidByte)(i => i.isValidByte)
getTypeTag((MyProg.prog.head._1)).tpe =:= ru.typeOf[(String) => Boolean] //>false!
So you see the problem.
To deal with it you can use heterogeneous lists. Lists and other various powerful structures you can find in shapeless: https://github.com/milessabin/shapeless

Function parameter types and =>

What exactly that declaration of method parameter means:
def myFunc(param: => Int) = param
What is meaning of => in upper definition?
This is so-called pass-by-name. It means you are passing a function that should return Int but is mostly used to implement lazy evaluation of parameters. It is somewhat similar to:
def myFunc(param: () => Int) = param
Here is an example. Consider an answer function returning some Int value:
def answer = { println("answer"); 40 }
And two functions, one taking Int and one taking Int by-name:
def eagerEval(x: Int) = { println("eager"); x; }
def lazyEval(x: => Int) = { println("lazy"); x; }
Now execute both of them using answer:
eagerEval(answer + 2)
> answer
> eager
lazyEval(answer + 2)
> lazy
> answer
The first case is obvious: before calling eagerEval() answer is evaluated and prints "answer" string. The second case is much more interesting. We are actually passing a function to lazyEval(). The lazyEval first prints "lazy" and evaluates the x parameter (actually, calls x function passed as a parameter).
See also
Scala Returning a void function with 0 parameters, ugly syntax?
Just to make sure there is an answer that uses the proper term: the Scala Language Specification uses the term call-by-name:
The type of a value parameter may be prefixed by =>, e.g. x: => T . The type of
such a parameter is then the parameterless method type => T . This indicates that
the corresponding argument is not evaluated at the point of function application, but
instead is evaluated at each use within the function. That is, the argument is
evaluated using call-by-name.
-- Section 4.6.1 of the Scala Language Specification
To add to Tomasz Nurkiewicz's answer above, the difference I encounter between () => Int and => Int is that the second allows calling with bare blocks:
scala> def myfunc(f : () => Int ) = println("Evaluated: " + f )
myfunc: (f: () => Int)Unit
scala> def myfunc2(f : => Int ) = println("Evaluated: " + f )
myfunc2: (f: => Int)Unit
scala> myfunc({1})
<console>:9: error: type mismatch;
found : Int(1)
required: () => Int
myfunc({1})
^
scala> myfunc2({1})
Evaluated: 1