字符串被视为 Monoid

发布于 2024-12-07 20:59:46 字数 541 浏览 0 评论 0原文

给定这样的签名或 那个

def foo[A, F[_]](implicit mon: Monoid[F[A]], pr: Pure[F]): F[A]

假设 A 是 Char,有没有办法获取 String 而不是 List[Char]?

String 不接受类型参数,所以我认为这是不可能的。下一个最佳选择是什么?现在,我对结果使用 mkString ,但这感觉不是最佳的。

我认为 String 是一个具有 0 ""append + 的幺半群。 。

Given a signature like this one or that one:

def foo[A, F[_]](implicit mon: Monoid[F[A]], pr: Pure[F]): F[A]

Assuming A is Char, is there a way to get a String instead of a List[Char]?

String does not take a type parameter, so I assume it's not possible. What's the next best option? Right now, I use mkString on the result, but that doesn't feel optimal.

I think String is a monoid with zero "" and append +...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

吲‖鸣 2024-12-14 20:59:46

可以说服 String 伪装成更高级的类型,从而允许使用 foo 形式的函数。但是,Scala 的类型推断目前无法完成推断 foo 类型参数的工作,因此您必须显式提供它们,

// Assuming the the definitions of Pure and Monoid from Scalaz

type ConstString = {
  type λ[X] = String
}

implicit def StringPure = new Pure[ConstString#λ] {
  def pure[A](a: => A) = a.toString
}

val sm = implicitly[Monoid[String]]
val sp = implicitly[Pure[ConstString#λ]]
val f : String = foo[Char, ConstString#λ](sm, sp) // OK

请注意 Char 类型foo 的参数未使用,可以是任何内容,但必须是某些内容:在这种情况下,Char 是自然选择,但 Nothing 或 < code>Any 也可以。

请注意,此解决方案利用了 String 的特殊特性:所有类型的值都可以转换为 String,因此 pure[A](a : => A ) : String 对于所有类型 A 都是可实现的。对于 String 以外的类型复制此习惯用法很可能必须利用某种机制来在 pure 主体中实现特定于类型的情况(例如某种模式匹配) )。

It is possible to persuade String to masquerade as a higher-kinded type, and hence allow functions of the form of foo to be applicable. However, Scala's type inference isn't currently up to the job of inferring foo's type arguments, so you'll have to supply them explicitly,

// Assuming the the definitions of Pure and Monoid from Scalaz

type ConstString = {
  type λ[X] = String
}

implicit def StringPure = new Pure[ConstString#λ] {
  def pure[A](a: => A) = a.toString
}

val sm = implicitly[Monoid[String]]
val sp = implicitly[Pure[ConstString#λ]]
val f : String = foo[Char, ConstString#λ](sm, sp) // OK

Note that the Char type argument to foo is unused and can be anything, but must be something: in this case either Char is the natural choice, but Nothing or Any would do as well.

Note that this solution trades on String's special characteristics: values of all types are convertible to Strings so pure[A](a : => A) : String is implementable for all types A. Replicating this idiom for types other than String would most likely have to exploit some mechanism for implementing type-specific cases in the body of pure (eg. a pattern match of some sort).

撩心不撩汉 2024-12-14 20:59:46

我能想到的最好的解决方案是定义从 List[Char]String 的隐式转换。

The best solution I can think of it is to define an implicit conversion from List[Char] to String.

染墨丶若流云 2024-12-14 20:59:46

根据你的分析,scala 的类型系统将拒绝 String,因为它不是“更高种类的类型”* -> * 是正确的。也就是说,对于任何 F, String 类型都不能分配给 F[_] 。您可以尝试(我没有检查这一点)隐式转换

def foo[A, F[_], That](implicit mon: Monoid[F[A]], pr: Pure[F], FA_Is_That: F[A] <%< That)

......但我怀疑这不会那么有用,因为您必须在需要时提供自己的定制转换,而且还因为假设这是代码的热门部分,性能会很糟糕。

或者,使用标准库,您可以使用 CanBuildFrom 机制,但它与 scalaz 风格类型类的混合效果如何很好还远不明显。

def foo[A, F[_], That](implicit mon: Monoid[F[A]], pr: Pure[F], b: CanBuildFrom[A, F[A], That]): That

当然,在方法主体中,您将需要使用构建器来构造返回值,而不是 Monoid/Pure 类型类,我怀疑这使得它们有些多余。

Your analysis, that scala's type-system will reject String as not being a "higher kinded type" * -> * is correct. That is, the type String is not assignable to F[_] for any F. You could try (I have not checked this) implicit conversions...

def foo[A, F[_], That](implicit mon: Monoid[F[A]], pr: Pure[F], FA_Is_That: F[A] <%< That)

...but this will not be that useful I suspect because you'd have to provide your own bespoke conversions where required but also because the performance would be terrible, assuming this is a hot part of the code.

Or, using the standard library, you could use the CanBuildFrom machinery but it's far from obvious how nicely this will mix with the scalaz-style typeclasses.

def foo[A, F[_], That](implicit mon: Monoid[F[A]], pr: Pure[F], b: CanBuildFrom[A, F[A], That]): That

In the body of the method, of course, you will need to use the builder to construct the return value, as opposed to the Monoid/Pure typeclasses, rendering them somewhat redundant, I suspect.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文