Scala中的Reader monad:返回,局部和顺序 [英] Reader monad in Scala: return, local, and sequence

查看:95
本文介绍了Scala中的Reader monad:返回,局部和顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在Scala中使用 scalaz Reader monad >图书馆.我对这个Monad熟悉,它在Haskell中定义.问题是我找不到等效于returnlocalsequence的功能(以及其他功能).

I'm using the Reader monad in Scala as provided by the scalaz library. I'm familiar with this monad as defined in Haskell. The problem is that I cannot find the functions equivalent to return, local, and sequence (among others).

当前我使用的是我不喜欢的结构,因为我在重复自己或使我的代码有些晦涩.

Currently I use constructs that I do not like since I'm repeating myself or making my code a bit obscure.

关于return,我当前正在使用:

Regarding return, I'm currently using:

Reader{_ => someValue}

我宁愿只使用像unit(someValue)这样的结构,但在互联网上找不到任何东西.像这一个这样的教程使用上述方法,但我认为不是最佳方法.

I'd rather just use a construct like unit(someValue), but I could not find anything on the internet. There are tutorials like this one that use the approach above, and which I consider not optimal.

关于local,我还必须执行类似的操作:而不是输入类似的内容:local f myReader我必须展开其定义:

Regarding local I also have to do something similar: instead of typing something like: local f myReader I have to unfold its definition:

Reader{env => myReader.run(f(env))

最后,顺序有点接近我的预期(作为一名Haskell难民在Scala工作):

Finally, sequence is a bit closer to what I would expect (being a Haskell refugee doing Scala):

readers: List[Reader[Env, T]]
readerTs: Reader[Env, List[T]] = readers.sequenceU

此实现的问题是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]]

看起来有点晦涩难懂,而且看起来像是黑魔法.理想情况下,我想在Monad上使用sequence操作.

appears like rather obscure, and seems like black magic. Ideally I would like to use a sequence operations on Monads.

在scalaz或类似的库中,是否可以将这些结构更好地翻译成Scala?我还没有嫁给任何用于Scala的Functional库,因此使用其他库的任何解决方案都可以,尽管我宁愿使用scalaz来解决问题,因为我已经使用它实现了代码.

Is there a better translation of these constructs to Scala available on scalaz or similar library? I'm not married to any Functional library for Scala, so any solution using other libraries will do, although I'd rather have an answer using scalaz, since I already implemented my code using it.

推荐答案

为了简化操作,我填写了一些类型.将它们更改为具有通用类型的def应该仍然有效. 另外,我提取了ReaderInt类型,以避免与lambdas类型混淆.

To make the things simpler, I fill in some types. Changing them to defs with generic types should still work. Also I extracted the ReaderInt type, to avoid confusion with type lambdas.

返回/纯/点

Scala没有自动的类型分类解析,因此您需要隐式提供它们.对于Kleisli(作为阅读器的monad转换器), Kleisli[Id, ?, ?]就足够了

Scala does not have automatic typeclass resolution, so you need to provide them implicitly. For Kleisli (being a monad transformer for reader), Kleisli[Id, ?, ?] is enough

 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是您的应用程序.

So as a general rule, you

1) import the applicative intance, which usually located in scalaz.std.something.somethingInstance

2) import scalaz.syntax.something._

3) then you can write x.point[F], where F is your applicative.

本地

不确定是否可以回答您的问题,但是Kleisli具有local方法.

local

Not sure, that it answers your question, but Kleisli has a local method.

val f: String ⇒ Int = _.length
val alwaysEleven = alwaysHello local f

测序

同样,您可以自由选择使用syntax或明确指定类型类.

sequencing

The same way, you are free to choose to use syntax for or to specify type classes explicitly.

  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很难找出正确的类型. 而且我个人认为自己自己输入某些类型并不麻烦.

I prefer not to use sequenceU, which uses Unapply typelcass to infer the G type, because sometimes scala has troubles of figuring out the right one. And I personally do not find it messy to put in some types myself.

尽管还没有太多内容,也许值得研究.

It may worth to look into cats, though it does not have much yet.

这篇关于Scala中的Reader monad:返回,局部和顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆