Reputation: 1499
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)
^
Upvotes: 0
Views: 213
Reputation: 6237
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.
Upvotes: 2