有没有什么快速的方法可以用作具体的功能(类型,比如说(A) => B)PartialFunction[A, B]?我所知道的最简洁的语法是:
(a: A) => a match { case obj => func(obj) }
Run Code Online (Sandbox Code Playgroud)
在任何地方都有隐式转换,例如:
implicit def funcAsPartial[A, B](func: A => B) = new PartialFunction[A, B] {
def isDefinedAt(a: A) = true
def apply(a: A) = func(a)
}
Run Code Online (Sandbox Code Playgroud)
我想我刚刚写了我要找的东西,但这已经存在于Scala库中吗?
通常,在收集与特定类型匹配的序列的所有元素时,生成的集合既具有原始集合的类型,又具有为以下类型选择的类型:
trait Foo
trait Bar
trait Baz {
// Works
def def1(foo: Seq[Foo]): Seq[Foo with Bar] =
foo collect {case foobar: Bar => foobar}
}
Run Code Online (Sandbox Code Playgroud)
当输入类型由有界成员类型参数化并且我想要的全部是由绑定类型(而不是成员类型)参数化的序列时,这甚至有效:
trait Baz {
type memberType <: Foo
// Works
def2(foo: Seq[memberType]): Seq[Foo with Bar] =
foo collect {case foobar: Bar => foobar}
}
Run Code Online (Sandbox Code Playgroud)
但是,当我真的想要返回由成员类型参数化的序列时,这会失败:
trait Baz {
type memberType <: Foo
// Fails
def def3(foo: Seq[memberType]): Seq[memberType with Bar] =
foo collect {case foobar: Bar => foobar}
}
Run Code Online (Sandbox Code Playgroud)
错误信息:
error: type mismatch;
found : …Run Code Online (Sandbox Code Playgroud) 定义 PF 有两种方法:1) 使用文字case {}语法,2) 作为显式类。我需要以下函数抛出 MatchError,但在第二种情况下不会发生。
1) 带外壳
val test: PartialFunction[Int, String] = {
case x if x > 100 => x.toString
}
Run Code Online (Sandbox Code Playgroud)
2)作为类
val test = new PartialFunction[Int, String] {
def isDefinedAt(x: Int) = x > 100
def apply(x: Int) = x.toString
}
Run Code Online (Sandbox Code Playgroud)
在秒的情况下,我应该手动调用吗?isDefinedAt编译器不应该隐式调用它吗?
我刚刚用Scala开始看似陡峭的学习曲线,并且无法完全理解"case"在部分函数中是如何工作的.
我查看了PartialFunction本身的定义,在那里我看到了如下的示例:
val isEven: PartialFunction[Int, String] = {
case x if x % 2 == 0 => x+" is even"
}
Run Code Online (Sandbox Code Playgroud)
我被卡住的部分是案例x,如果x%2 - Scala如何知道这是什么?这个"case"语句/关键字的正式定义是什么?
我认为我混淆的一个原因是因为在Lift中我看到类似下面的内容(在Actor类中):
override def messageHandler = {
case SomeKindOfUserMessageClass(id1, param1) => ....
case AnotherKindOfUserMessageClass(id2) => ....
}
Run Code Online (Sandbox Code Playgroud)
我直觉地理解这里发生了什么,但是我无法对"案例"的使用方式进行某种统一的定义.对我来说更令人费解的是Scala编译器如何解开这一切.
我对Scala很新,但我已经爱上了它.我已经阅读了有关部分功能的教程和文章.我想要实现的是让一个对象扩展PartialFunction [...,...]并直接用case定义它,而不需要定义isDefinedAt和apply方法.
例如
val partialfuncval : PartialFunction[Int,Boolean] = {
case 1 => false
}
Run Code Online (Sandbox Code Playgroud)
是部分函数的有效定义.但为什么我不能写
object PartialFunctionClass extends PartialFunction[Int,Boolean] {
case 1 => false
}
Run Code Online (Sandbox Code Playgroud)
?这将取消定义isDefinedAt和apply的需要,并且会使得编写某些类的类(由我正在使用的lib预定义)类型更容易.
让我们定义一个PartialFunction[String, String]和一个PartialFunction[Any, String]
现在,给定定义 orElse
def orElse[A1 <: A, B1 >: B](that: PartialFunction[A1, B1]): PartialFunction[A1, B1]
Run Code Online (Sandbox Code Playgroud)
我希望不能把这两者组合起来,因为
A→交通String
A1→交通Any
因此,约束A1 <: A(即Any <: String)不成立.
出乎意料的是,我可以编写它们并获得PartialFunction[String, String]整个String域的定义.这是一个例子:
val a: PartialFunction[String, String] = { case "someString" => "some other string" }
// a: PartialFunction[String,String] = <function1>
val b: PartialFunction[Any, String] = { case _ => "default" }
// b: PartialFunction[Any,String] = <function1>
val c = a orElse …Run Code Online (Sandbox Code Playgroud) 我目前正在学习 Scala,我只是想知道左折叠。由于左折叠是柯里化的,因此您应该能够获得带有第一个参数的部分应用函数(PAF),如下所示。
(0 /: List(1, 2, 3)) _
Run Code Online (Sandbox Code Playgroud)
但实际上,我有一个错误。
<console>:8: error: missing arguments for method /: in trait TraversableOnce;
follow this method with `_' if you want to treat it as a partially applied function
Run Code Online (Sandbox Code Playgroud)
然后我通过向右折叠尝试了同样的事情,如下所示
(List(1, 2, 3) :\ 0) _
Run Code Online (Sandbox Code Playgroud)
这样,它就正确了,我可以得到一个PAF,例如((Int, Int) => Int) => Int
我知道我可以通过使用foldLeft方法获得PAF,但我想知道是否可以用“/:”来表达它。
我想我错过了一些东西:
scala> Some(1) collect ({ case n if n > 0 => n + 1; case _ => 0})
res0: Option[Int] = Some(2)
scala> None collect ({ case n if n > 0 => n + 1; case _ => 0})
<console>:6: error: value > is not a member of Nothing
None collect ({ case n if n > 0 => n + 1; case _ => 0})
^
<console>:6: error: value + is not a member of Nothing
None …Run Code Online (Sandbox Code Playgroud) 在Learn you a Haskell 中,给出了以下示例:
map ($ 3) [(4+), (10*), (^2), sqrt]
[7.0,30.0,9.0,1.7320508075688772]
Run Code Online (Sandbox Code Playgroud)
但是,我不明白为什么会这样。
函数的签名是
Prelude> :info ($)
($) :: (a -> b) -> a -> b
Prelude> :t ($ 3)
($ 3) :: Num a => (a -> b) -> b
Run Code Online (Sandbox Code Playgroud)
然而,->是一个左结合运营商,所以$ :: (a -> b) -> a -> b实际上((($ :: (a-b))-> a)-> b),所以不宜3在($ 3)对应(a->b)的功能是函数的第一个“变量” $?即为什么是($ 3)签名的函数(a -> b) -> b …
我不明白为什么使用变量作为临时值会使部分函数不同:
val f1: PartialFunction[Option[Int], Int] = { b =>
val i = identity(b)
i match {
case Some(res) => res
}
}
val f2: PartialFunction[Option[Int], Int] = { b =>
identity(b) match {
case Some(res) => res
}
}
f1.isDefinedAt(None)
f2.isDefinedAt(None)
Run Code Online (Sandbox Code Playgroud)
Scala 2.13.12 和 Scala 3.3.1 的结果是true/ 。false第一个版本显示匹配详尽性警告,第二个版本则没有。该代码无法使用 Scala 2.12.18 编译,错误出现在第一个版本中:
类型不匹配;
找到:选项[Int] => Int
必需:PartialFunction[Option[Int],Int]
第二个版本怎么比第一个版本更“偏颇”呢?