Reader Scala 中的 monad:return、局部和序列
Reader monad in Scala: return, local, and sequence
我在 Scala 中使用 scalaz library. I'm familiar with this monad as defined in Haskell 提供的 Reader
monad。问题是我找不到等同于 return
、local
和 sequence
(以及其他)的函数。
目前我使用我不喜欢的结构,因为我在重复自己或使我的代码有点晦涩难懂。
关于return
,我目前正在使用:
Reader{_ => someValue}
我宁愿只使用像 unit(someValue)
这样的结构,但我在 Internet 上找不到任何东西。有像 this one 这样的教程使用上述方法,我认为这不是最佳方法。
关于 local
我也必须做类似的事情:而不是输入类似的东西:local f myReader
我必须展开它的定义:
Reader{env => myReader.run(f(env))
最后,序列有点接近我的预期(作为一个 Haskell 难民使用 Scala):
readers: List[Reader[Env, T]]
readerTs: Reader[Env, List[T]] = readers.sequenceU
我对这个实现的问题是,作为 Scala 的新手,sequenceU
的类型
final class TraverseOps[F[_],A] private[syntax](val self: F[A])(implicit val F: Traverse[F]) extends Ops[F[A]] {
//...
def sequenceU(implicit G: Unapply[Applicative, A]): G.M[F[G.A]]
看起来有点晦涩难懂,看起来像是黑魔法。理想情况下,我想对 Monads 使用 sequence
操作。
在 scalaz 或类似库中是否有更好的将这些结构转换为 Scala 的方法?我没有与 Scala 的任何函数式库结婚,所以使用其他库的任何解决方案都可以,尽管我宁愿使用 scalaz 得到答案,因为我已经使用它实现了我的代码。
为了简单起见,我填写了一些类型。将它们更改为具有通用类型的 defs 应该仍然有效。
我还提取了 ReaderInt
类型,以避免与 lambdas 类型混淆。
return/纯/点
Scala 没有自动类型类解析,因此您需要隐式提供它们。对于 Kleisli
(作为 reader 的 monad 转换器),
Kleisli[Id, ?, ?]
够了
implicit val KA = scalaz.Kleisli.kleisliIdApplicative[Int]
type ReaderInt[A] = Kleisli[Id.Id, Int, A]
val alwaysHello = KA.point("hello")
或使用导入语法:
import scalaz.syntax.applicative._
val alwaysHello = "hello".point[ReaderInt]
因此,作为一般规则,您
1) 导入应用实例,通常位于scalaz.std.something.somethingInstance
2) import scalaz.syntax.something._
3)然后你可以写x.point[F]
,其中F
是你的应用程序。
本地
不确定,它是否回答了您的问题,但是 Kleisli
有一个 local
方法。
val f: String ⇒ Int = _.length
val alwaysEleven = alwaysHello local f
测序
同样,您可以自由选择使用 syntax
或明确指定类型 类。
import scalaz.std.list.listInstance
val initial: List[ReaderInt[String]] = ???
val sequenced: ReaderInt[List[String]] = Traverse[List].sequence[ReaderInt, String](initial)
import scalaz.syntax.traverse._
val z = x.sequence[ReaderInt, String]
我不喜欢使用 sequenceU
,它使用 Unapply
typelcass 来推断 G
类型,因为有时 scala 很难找出正确的类型。
而且我个人并不觉得自己输入一些类型很乱。
可能值得研究一下 cats,尽管还没有太多。
我在 Scala 中使用 scalaz library. I'm familiar with this monad as defined in Haskell 提供的 Reader
monad。问题是我找不到等同于 return
、local
和 sequence
(以及其他)的函数。
目前我使用我不喜欢的结构,因为我在重复自己或使我的代码有点晦涩难懂。
关于return
,我目前正在使用:
Reader{_ => someValue}
我宁愿只使用像 unit(someValue)
这样的结构,但我在 Internet 上找不到任何东西。有像 this one 这样的教程使用上述方法,我认为这不是最佳方法。
关于 local
我也必须做类似的事情:而不是输入类似的东西:local f myReader
我必须展开它的定义:
Reader{env => myReader.run(f(env))
最后,序列有点接近我的预期(作为一个 Haskell 难民使用 Scala):
readers: List[Reader[Env, T]]
readerTs: Reader[Env, List[T]] = readers.sequenceU
我对这个实现的问题是,作为 Scala 的新手,sequenceU
final class TraverseOps[F[_],A] private[syntax](val self: F[A])(implicit val F: Traverse[F]) extends Ops[F[A]] {
//...
def sequenceU(implicit G: Unapply[Applicative, A]): G.M[F[G.A]]
看起来有点晦涩难懂,看起来像是黑魔法。理想情况下,我想对 Monads 使用 sequence
操作。
在 scalaz 或类似库中是否有更好的将这些结构转换为 Scala 的方法?我没有与 Scala 的任何函数式库结婚,所以使用其他库的任何解决方案都可以,尽管我宁愿使用 scalaz 得到答案,因为我已经使用它实现了我的代码。
为了简单起见,我填写了一些类型。将它们更改为具有通用类型的 defs 应该仍然有效。
我还提取了 ReaderInt
类型,以避免与 lambdas 类型混淆。
return/纯/点
Scala 没有自动类型类解析,因此您需要隐式提供它们。对于 Kleisli
(作为 reader 的 monad 转换器),
Kleisli[Id, ?, ?]
够了
implicit val KA = scalaz.Kleisli.kleisliIdApplicative[Int]
type ReaderInt[A] = Kleisli[Id.Id, Int, A]
val alwaysHello = KA.point("hello")
或使用导入语法:
import scalaz.syntax.applicative._
val alwaysHello = "hello".point[ReaderInt]
因此,作为一般规则,您
1) 导入应用实例,通常位于scalaz.std.something.somethingInstance
2) import scalaz.syntax.something._
3)然后你可以写x.point[F]
,其中F
是你的应用程序。
本地
不确定,它是否回答了您的问题,但是 Kleisli
有一个 local
方法。
val f: String ⇒ Int = _.length
val alwaysEleven = alwaysHello local f
测序
同样,您可以自由选择使用 syntax
或明确指定类型 类。
import scalaz.std.list.listInstance
val initial: List[ReaderInt[String]] = ???
val sequenced: ReaderInt[List[String]] = Traverse[List].sequence[ReaderInt, String](initial)
import scalaz.syntax.traverse._
val z = x.sequence[ReaderInt, String]
我不喜欢使用 sequenceU
,它使用 Unapply
typelcass 来推断 G
类型,因为有时 scala 很难找出正确的类型。
而且我个人并不觉得自己输入一些类型很乱。
可能值得研究一下 cats,尽管还没有太多。