Scalaz Writer Monad 和 filterM
Scalaz Writer Monad and filterM
我正在研究 learning scalaz and Learn You A Haskell For Greater Good 并且想知道如何将 filterM 示例从 LYAHFGG 转换为 Scala。
fst $ runWriter $ filterM keepSmall [9,1,5,2,10,3]
keepSmall
定义为
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
我的天真方法以编译错误告终,我不知道如何解决这个问题!
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)
编译错误:
Error:(182, 32) no type parameters for method filterM: (p: Int => M[Boolean])(implicit evidence: 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)
^
和
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)
^
问题是由于 Scala 无法真正知道如何将具有三个 孔 的类型放入 filterM
预期的参数中,该参数具有只有一个 孔 填充了一个 Boolean
.
您可以使用像这样的一些奇怪的 type-lambda 语法来解决您的问题(未经测试,可能不起作用):
val keepSmall: (Int => ({type L[T] = WriterT[Id, Vector[String], T]})#L) = ...
或者(更容易)通过引入类型别名如下:
type MyWriter[T] = WriterT[Id, Vector[String], T]
val keepSmall: (Int => MyWriter[Boolean]) = ...
这将确保 filterM
期望的参数类型与您提供的参数类型匹配。
我正在研究 learning scalaz and Learn You A Haskell For Greater Good 并且想知道如何将 filterM 示例从 LYAHFGG 转换为 Scala。
fst $ runWriter $ filterM keepSmall [9,1,5,2,10,3]
keepSmall
定义为
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
我的天真方法以编译错误告终,我不知道如何解决这个问题!
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)
编译错误:
Error:(182, 32) no type parameters for method filterM: (p: Int => M[Boolean])(implicit evidence: 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)
^
和
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)
^
问题是由于 Scala 无法真正知道如何将具有三个 孔 的类型放入 filterM
预期的参数中,该参数具有只有一个 孔 填充了一个 Boolean
.
您可以使用像这样的一些奇怪的 type-lambda 语法来解决您的问题(未经测试,可能不起作用):
val keepSmall: (Int => ({type L[T] = WriterT[Id, Vector[String], T]})#L) = ...
或者(更容易)通过引入类型别名如下:
type MyWriter[T] = WriterT[Id, Vector[String], T]
val keepSmall: (Int => MyWriter[Boolean]) = ...
这将确保 filterM
期望的参数类型与您提供的参数类型匹配。