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

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

问题描述

有时,当我阅读Scala生态系统中的文章时,我读到了提升/提升的术语。不幸的是,它没有解释到底是什么意思。我做了一些研究,似乎解除与功能值或类似的东西有关,但我无法找到一个文本解释以新手友好的方式实际提升的内容。



电梯框架,它的名字取消了,但并没有帮助回答这个问题。



什么是Scala中的提升?

解决方案

有几个用法:
$ b

PartialFunction



记住 PartialFunction [A,B] 是为域 A (由 isDefinedAt 方法指定)。您可以将 PartialFunction [A,B] 提升为函数[A,Option [B]] 。也就是定义在 A 整个上的一个函数,但其​​值是 Option [B] $ b

这是通过显式调用方法 lift 来完成的, 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] =无

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



方法



您可以将方法调用提升为一个函数。这叫做 eta-expansion (感谢Ben James)。举例来说:

  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

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



函子



函数(由 scalaz 定义)是某个容器(我使用非常宽松的), F 如果我们有一个 F [A] 和一个函数 A => B ,那么我们可以得到一个 F [B] (想想,例如, F = List map 方法)

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

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

这是同构的能够提升功能 A => B 放入函子的域中。那就是:

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

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



Monad变形金刚



hcoopz 在下面说(我刚刚意识到这样可以节省大量的不必要的代码),术语lift也有意义在 Monad变形金刚中。回想一下,monad变形金刚是一种叠加monad的方式(单体不合成)。

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

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

或者:

  iob.liftM [StreamT] 

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

  lazy val f:(A,B)=> C = ??? 
val cs =
用于{
a < - as // // as StreamT [IO,A]
b< - bs.liftM [StreamT] // bs只是一个IO [B]
}
产生f(a,b)

cs.toStream //是一个Stream [IO [C]],cs是一个StreamT [IO ,C]


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.

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

What is "lifting" in Scala?

解决方案

There are a few usages:

PartialFunction

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]

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)

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

We lift a method into a function by applying the underscore

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

scala> f(4)
res0: Int = 8

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

Functors

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]
}

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]

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.

Monad Transformers

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).

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)))

Or this:

iob.liftM[StreamT]

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天全站免登陆