给出一个假的F
类型类:
scala> trait F[A] {}
defined trait F
此定义使用context bound
要求输入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")
^
然后我使用:
定义了F[String]
scala> implicit def fInstance(x: String) = new F[String] {}
fInstance: (x: String)F[String]
但是,我无法运行:
scala> f("foobar")
<console>:18: error: could not find implicit value for evidence parameter of type F[String]
f("foobar")
^
因为我没有隐式F[String]
,而是String => F[String]
。
使用这样的implicit def
来满足F[String]
约束的正确方法是什么,即使用f
类型成功调用String
函数?
我通过以下方式开始工作:
scala> implicit val x: F[String] = implicitly[String => F[String]].apply("foobar")
x: F[String] = $anon$1@7b7fdc8
scala> f("foobar")
scala.NotImplementedError: an implementation is missing
at scala.Predef$.$qmark$qmark$qmark(Predef.scala:230)
at .f(<console>:12)
... 33 elided
但我不确定它是否是正确/干净的方式。
答案 0 :(得分:1)
您定义了隐式转化。如果你想使用def来提供类型类实例,你只需编写相同的内容即可编写隐式val,但用def替换val。
arr1
通常你只需要使用def,如果你需要类型参数,就像这里一样。
import xlwings as xw
import win32api
def msg_box():
wb = xw.Book.caller()
win32api.MessageBox(wb.app.hwnd, "YourMessage")
或者
implicit def fInstance = new F[String] {}
答案 1 :(得分:0)
您的fInstance
定义了隐式转化,即将String
转换为F[String]
的方法。为了生成类型类实例,可以使用接受隐式参数的方法:
implicit def fInstance(implicit x: String) = new F[String] {}
它通常在FP库中用于从另一个派生类型类派生:
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]
可以对任何String进行操作,而不依赖于提供给函数的实际参数。当然,您始终可以明确提供实例:
f("foobar")(new F[String] { })
作为后续行动,类型类的重要部分是你可以临时定义它们,即根本无法访问F
和String
的定义,你被迫范围隐含在Scala中并导入它们,所以它完全没问题。
答案 2 :(得分:0)
以下是您的定义的更简单版本(您可以从implicit
删除fInstance
):
implicit val singleFInstance: F[String] = fInstance("") // or fInstance("foobar"), etc.
这是否是正确的做法,在很大程度上取决于F
和f
应该是什么意思。
但一般来说:如果F
实际上是一个类型类,fInstance(string)
根据字符串(不仅仅是不同的实例,但行为不同)给出不同的结果,f
& #39;签名是正确的,那么这是错误的,你应该接受调用f("foobar")
没有意义。