首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类型类型的类型*的类型实例*,其中期望类型* -> *

类型类型的类型*的类型实例*,其中期望类型* -> *
EN

Stack Overflow用户
提问于 2016-03-17 12:34:09
回答 1查看 71关注 0票数 2

我正在尝试为String创建一个scalaz的String类型的实例。到目前为止,这就是我所得到的:

代码语言:javascript
复制
implicit val stringIsEmpty = new IsEmpty[({ type t[+A] = String })#t] {
  def isEmpty[A](fa: String) = ???
  def empty[A] = ???
  def plus[A](a: String, b: => String) = ???
}

def f[F[_]: IsEmpty, A](fa: F[A]): F[A] = fa

现在,String是类*,而IsEmpty[F]期望F是类* -> *,因此类型为lambda f[+A] = String

这是可行的,但只有当字符串被键入为t时才能工作,即:

代码语言:javascript
复制
// doesn't compile
f("hello")

// compiles if I extract `t` into a type alias and annotate the string with it
type t[+A] = String
implicit val stringIsEmpty = new IsEmpty[t] { /** **/ }

f("hello": t[Nothing])

是否有任何方法来实现IsEmpty,使我能够将f应用于一个正常的字符串?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-03-17 19:59:13

事实证明,您可以使用Unapply魔术将一种类型的*转换成一种类型的* -> *

这是我的解决方案:

代码语言:javascript
复制
def f[F[_]: IsEmpty, A](fa: F[A]): F[A] = fa

def fU[FA](fa: FA)(implicit U: Unapply[IsEmpty, FA]) =
  f[U.M, U.A](U(fa))(U.TC)

现在你可以直接做fU("hello")了。返回类型也将被正确地推断为String

据我所知,您确实需要这个辅助函数,这有点痛苦,但我想这就是缺少直接编译器支持。所要付出的代价

当我意识到Applicative有一个用于String的实例,并且您可以做"hello".replicateM(3)之类的事情时,我就有了这个想法。

我把这句话具体化如下:

代码语言:javascript
复制
scala> import scala.reflect.runtime.universe
import scala.reflect.runtime.universe

scala> universe.reify("hello".replicateM(3)).tree
res32: reflect.runtime.universe.Tree = Scalaz.ToApplicativeOpsUnapply("hello")(Unapply.unapplyA(Applicative.monoidApplicat
ive(Scalaz.stringInstance))).replicateM(3)

ToApplicativeOpsUnapply在幕后透露了这个秘密:

代码语言:javascript
复制
implicit def ToApplicativeOpsUnapply[FA](v: FA)(implicit F0: Unapply[Applicative, FA]) =
  new ApplicativeOps[F0.M,F0.A](F0(v))(F0.TC)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36060690

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档