什么是“举"?在斯卡拉? [英] What is "lifting" in Scala?

查看:27
本文介绍了什么是“举"?在斯卡拉?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有时当我阅读 Scala 生态系统中的文章时,我会读到提升"/提升"这个词.不幸的是,没有解释这究竟意味着什么.我做了一些研究,似乎提升与功能价值或类似的东西有关,但我无法找到以初学者友好的方式解释提升实际上是什么的文本.

Sometimes when I read articles in the Scala ecosystem I read the term "lifting" / "lifted". Unfortunately, it is not explained what that exactly means. I did some research, and it seems that lifting has something to do with functional values or something like that, but I was not able to find a text that explains what lifting actually is about in a beginner friendly way.

Lift 框架存在额外的混淆,该框架的名称有提升,但它没有t 帮助回答问题.

There is additional confusion through the Lift framework which has lifting in its name, but it doesn't help answer the question.

Scala 中的提升"是什么?

推荐答案

有几个用法:

记住 PartialFunction[A, B] 是为域 A 的某个子集定义的函数(由 isDefinedAt 方法指定)).你可以提升"一个 PartialFunction[A, B] 到一个 Function[A, Option[B]].也就是说,在 A整体 上定义的函数,但其​​值的类型为 Option[B]

Remember a PartialFunction[A, B] is a function defined for some subset of the domain A (as specified by the isDefinedAt method). You can "lift" a PartialFunction[A, B] into a Function[A, Option[B]]. That is, a function defined over the whole of A but whose values are of type Option[B]

这是通过显式调用 PartialFunction 上的方法 lift 来完成的.

This is done by the explicit invocation of the method lift on PartialFunction.

scala> val pf: PartialFunction[Int, Boolean] = { case i if i > 0 => i % 2 == 0}
pf: PartialFunction[Int,Boolean] = <function1>

scala> pf.lift
res1: Int => Option[Boolean] = <function1>

scala> res1(-1)
res2: Option[Boolean] = None

scala> res1(1)
res3: Option[Boolean] = Some(false)

方法

您可以将方法调用提升"为函数.这称为 eta-expansion(感谢 Ben James).例如:

Methods

You can "lift" a method invocation into a function. This is called eta-expansion (thanks to Ben James for this). So for example:

scala> def times2(i: Int) = i * 2
times2: (i: Int)Int

我们通过应用下划线

scala> val f = times2 _
f: Int => Int = <function1>

scala> f(4)
res0: Int = 8

注意方法和函数之间的根本区别.res0 是(函数)类型 (Int => Int) 的一个实例(即它是一个)代码>

Note the fundamental difference between methods and functions. res0 is an instance (i.e. it is a value) of the (function) type (Int => Int)

函子(由 scalaz 定义)是某种容器"(我使用术语非常 松散地),F 这样,如果我们有一个 F[A] 和一个函数 A =>;B,然后我们可以得到一个 F[B](例如,F = Listmap> 方法)

A functor (as defined by scalaz) is some "container" (I use the term extremely loosely), F such that, if we have an F[A] and a function A => B, then we can get our hands on an F[B] (think, for example, F = List and the map method)

我们可以对这个属性进行如下编码:

We can encode this property as follows:

trait Functor[F[_]] { 
  def map[A, B](fa: F[A])(f: A => B): F[B]
}

这与能够提升"函数A =>B 进入函子的域.即:

This is isomorphic to being able to "lift" the function A => B into the domain of the functor. That is:

def lift[F[_]: Functor, A, B](f: A => B): F[A] => F[B]

也就是说,如果 F 是一个函子,并且我们有一个函数 A =>B,我们有一个函数F[A] =>F[B].您可以尝试实施 lift 方法 - 这非常简单.

That is, if F is a functor, and we have a function A => B, we have a function F[A] => F[B]. You might try and implement the lift method - it's pretty trivial.

正如 hcoopz 在下面所说的(我刚刚意识到这会让我免于编写大量不必要的代码),术语lift"在 Monad 中也有含义变形金刚.回想一下,monad 转换器是一种将 monad 彼此堆叠"的方式(monad 不构成).

As hcoopz says below (and I've just realized that this would have saved me from writing a ton of unnecessary code), the term "lift" also has a meaning within Monad Transformers. Recall that a monad transformers are a way of "stacking" monads on top of each other (monads do not compose).

例如,假设您有一个返回 IO[Stream[A]] 的函数.这可以转换为 monad 转换器 StreamT[IO, A].现在,您可能希望将 IO[B] 的其他值提升"为它也是 StreamT.你可以这样写:

So for example, suppose you have a function which returns an IO[Stream[A]]. This can be converted to the monad transformer StreamT[IO, A]. Now you may wish to "lift" some other value an IO[B] perhaps to that it is also a StreamT. You could either write this:

StreamT.fromStream(iob map (b => Stream(b)))

或者这个:

iob.liftM[StreamT]

这就引出了一个问题:为什么我要将 IO[B] 转换为 StreamT[IO, B]?.答案是利用组合的可能性".假设你有一个函数 f: (A, B) =>C

this begs the question: why do I want to convert an IO[B] into a StreamT[IO, B]?. The answer would be "to take advantage of composition possibilities". Let's say you have a function f: (A, B) => C

lazy val f: (A, B) => C = ???
val cs = 
  for {
    a <- as                //as is a StreamT[IO, A]
    b <- bs.liftM[StreamT] //bs was just an IO[B]
  }
  yield f(a, b)

cs.toStream //is a Stream[IO[C]], cs was a StreamT[IO, C]

这篇关于什么是“举"?在斯卡拉?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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