【问题标题】:String seen as a Monoid字符串被视为 Monoid
【发布时间】:2011-10-03 06:51:13
【问题描述】:

给出这样的签名或that one

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

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

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

我认为String 是一个具有 ""附加 +...

的幺半群

【问题讨论】:

  • 为什么需要 Monoid[F[A]] 而不仅仅是 Monoid[F]?
  • @CheatEx,在这种情况下,我不是写foo的人,我只是调用者。

标签: scala scalaz


【解决方案1】:

可以说服 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

请注意,fooChar 类型参数未使用,可以是任何东西,但必须是某种东西:在这种情况下,Char 是自然选择,但 NothingAny 会这样做好吧。

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

【讨论】:

  • 但是implicitly[Pure[ConstString#λ]].pure('a') 会返回空字符串,所以这并没有多大用处。是吗?
  • 当然,你需要一个不同的Pure[ConstString#λ] 定义来做任何有用的工作。已编辑答案以反映这一点。
  • @DanielC.Sobral 你确实做到了:-)
  • 我建议a.asInstanceOf[String] 反映StringPure 有点作弊的事实。
  • @retronym 是的,由于String 的特殊特性,我同意这是一个特殊情况。我已经编辑了答案以反映这一点,但我认为坚持 .asInstanceOf[String] 有点 OTT ;-)
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    您的分析,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 类型类,我怀疑它们会显得有些多余。

    【讨论】:

      猜你喜欢
      • 2014-11-01
      • 1970-01-01
      • 2021-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-26
      • 1970-01-01
      • 2017-11-20
      相关资源
      最近更新 更多