简体   繁体   English

如何使用scalaz的“标记的类型”替换我的类型别名?

[英]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 typehttp ://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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM