[英]How to use scalaz's `Tagged Type` to replace my type alias?
I want to define objects as functions and depend it in other functions: 我想将对象定义为函数,并将其依赖于其他函数:
type FetchPage = String => String
type FindImages = String => List[String]
object WillFetchPage extends FetchPage {
def apply(url:String):String = /* get content of the url */
}
class WillFindImages(fetchPage: FetchPage) extends FindImages {
def apply(url:String):List[String] = {
val html = fetchPage(url)
// get image srcs from the <img> tags
}
}
Then I can inject WillFetchPage
to WillFindImages
: 然后我可以将WillFetchPage
注入WillFindImages
:
val findImages = new WillFindImages(WillFetchPage)
Also test WillFindImages
easily by injecting a mock function: 还可以通过注入一个模拟函数WillFindImages
轻松测试WillFindImages
:
val testFindImages = new WillFindImages(_ => "html-have-3-images")
val images = testFindImages("any-url")
// assertion
You can see the type alias FetchPage
is just a type alias, so I can pass other String => String
functions to WillFindImages
by mistake, so I'm looking for a type-safe solution. 您可以看到类型别名FetchPage
只是类型别名,因此我可以错误地将其他String => String
函数传递给WillFindImages
,因此我正在寻找一种类型安全的解决方案。
Then I heard of Tagged type
from scalaz: http://eed3si9n.com/learning-scalaz/Tagged+type.html 然后我从scalaz听说了Tagged type
: http ://eed3si9n.com/learning-scalaz/Tagged+type.html
The example is exciting: 该示例令人兴奋:
sealed trait KiloGram
def KiloGram[A](a: A): A @@ KiloGram = Tag[A, KiloGram](a)
val mass = KiloGram(20.0)
2 * mass
You can see the mass
here is actually a double 20.0
, but it has some unique type. 您可以看到这里的mass
实际上是20.0
的两倍,但是它具有一些唯一的类型。
I want to use it to improve my code, but sadly I can't find a way to do it. 我想用它来改进我的代码,但可惜我找不到一种方法。 I tried: 我试过了:
object FetchPage extends ((String => Try[String]) @@ FetchType)
But it provides an compilation error: 但是它提供了一个编译错误:
Error:(18, 51) class type required but String => scala.util.Try[String] with
scalaz.Tagged[object_as_func.FetchType] found
object FetchPage extends ((String => Try[String]) @@ FetchType) {
^
How to fix it? 如何解决?
What scalaz version do you use? 您使用什么scalaz版本? It's a bit different in 7.0.6 and 7.1.0. 在7.0.6和7.1.0中有所不同。 Here is example for 7.1.0 这是7.1.0的示例
import scalaz.@@
object PageFetcher
type FetchPage = String => String
type FindImages = String => List[String]
val WillFetchPage: FetchPage @@ PageFetcher.type =
scalaz.Tag[FetchPage, PageFetcher.type](url => "Content")
class WillFindImages(fetchPage: FetchPage @@ PageFetcher.type) extends FindImages {
def apply(url: String): List[String] = scalaz.Tag.unwrap(fetchPage)(url).grouped(1).toList
}
val images = new WillFindImages(WillFetchPage)("url")
println(images)
val testFetcher: FetchPage @@ PageFetcher.type =
scalaz.Tag[FetchPage, PageFetcher.type](url => "TestContent")
val testImages = new WillFindImages(testFetcher)("url")
println(testImages)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.