Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/31.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 使用`隐式定义`_Scala_Typeclass - Fatal编程技术网

Scala 使用`隐式定义`

Scala 使用`隐式定义`,scala,typeclass,Scala,Typeclass,给定一个组合的F类型类别: scala> trait F[A] {} defined trait F 此定义使用上下文绑定要求输入a具有类型类实例F: scala> def f[A : F](x: A) = ??? f: [A](x: A)(implicit evidence$1: F[A])Nothing 我定义了一个Person并键入类实例: scala> case class Person(name: String) defined class Person sca

给定一个组合的
F
类型类别:

scala> trait F[A] {}
defined trait F
此定义使用
上下文绑定
要求输入
a
具有类型类实例
F

scala> def f[A : F](x: A) = ???
f: [A](x: A)(implicit evidence$1: F[A])Nothing
我定义了一个
Person
并键入类实例:

scala> case class Person(name: String)
defined class Person

scala> implicit val person: F[Person] = new F[Person] {}
person: F[Person] = $anon$1@262b2c86
汇编如下:

scala> f(Person("foo"))
scala.NotImplementedError: an implementation is missing
但是,没有
String
实现,所以它失败了

scala> f("foobar")
<console>:17: error: could not find implicit value for evidence parameter of type F[String]
       f("foobar")
        ^
但是,我不能跑:

scala> f("foobar")
<console>:18: error: could not find implicit value for evidence parameter of type F[String]
       f("foobar")
        ^

但是我不确定这样做是否正确/干净。

您的
fInstance
定义了一种隐式转换,即将
字符串
转换为
F[String]
。要生成typeclass实例,可以使用接受隐式参数的方法:

implicit def fInstance(implicit x: String) = new F[String] {}
它通常在FP库中用于从一个typeclass派生另一个typeclass:

implicit def optionMonoid[A](implicit S: Semigroup[A]): Monoid[Option[A]] = ???
// or, which is the same
// implicit def optionMonoid[A: Semigroup]: Monoid[Option[A]] = ???
其思想是,
F[String]
通常可以对任何字符串进行操作,而不依赖于函数中提供的实际参数。当然,您始终可以显式地提供实例:

f("foobar")(new F[String] { })

作为后续工作,TypeClass的重要部分是您可以临时定义它们,即根本无法访问
F
String
的定义,并且您必须在Scala中定义隐式并导入它们,所以这完全没问题。

您定义了隐式转换。如果您想使用def来提供typeclass实例,只需编写与编写隐式val相同的内容,但用def替换val即可

implicit def fInstance = new F[String] {}
通常,只有在需要类型参数时才使用def,如下所示

implicit def fInstance[A] = new F[List[A]] {}


以下是您定义的一个简单版本(您可以从
fInstance
中删除
隐式
):

这是否正确,很大程度上取决于
F
F
的含义


但一般来说:如果
F
确实是一个类型类,
fInstance(string)
根据字符串给出不同的结果(不仅是不同的实例,还有不同的行为),并且
F
的签名是正确的,那么这是错误的,您应该接受调用
F(“foobar”)
没有意义。

如果不知道type类要捕获哪些信息和操作,那么很难回答这个问题,但是考虑到这个特殊的
F
,您可以用与
Person
实例完全相同的方式定义
字符串
实例。在这种情况下,我只能构造
F[String]
如果提供了
字符串,即
F[String]
实例依赖于
字符串
参数。接下来,在伴生类之外使用
隐式
是否不好,即孤立的
隐式
实例?
fInstance
不是typeclass实例,而是隐式转换
,您必须在Scala中定义隐式并导入它们,因此它是这完全没问题。
你能说一下这句话是如何应用于(或不应用于)孤儿
隐式
的吗?@KevinMeredith你不能简单地在源代码中写
def
val
(如果是应用程序代码而不是Scala脚本的话)-它必须属于一个对象或类。因此,您必须使用
对象隐式{implicit def fString:F[String]=???}
,但您不能在其他代码中使用它,除非在使用之前在其中导入隐式.fString
implicit def fInstance = new F[String] {}
implicit def fInstance[A] = new F[List[A]] {}
implicit def fInstance[A](implicit ev: F[A]) = new F[List[A]] {}
implicit val singleFInstance: F[String] = fInstance("") // or fInstance("foobar"), etc.