【问题标题】:traverse a string in cats/scalaz在cats/scalaz中遍历一个字符串
【发布时间】:2018-10-07 17:46:49
【问题描述】:

我想通过以下方式遍历一个String:

import cats.implicits._

object RnaTranscription {
  val mMap: Map[Char, Option[Char]] =
    Map('G' -> Some('C'),
        'C' -> Some('G'),
        'T' -> Some('A'),
        'A' -> Some('U')).withDefaultValue(None)

  def toRna(dna: String): Option[String] = {
    dna.toList.traverse(mMap).map(_.mkString)
  }
}

但它有额外的步骤,我需要先转换为List[Char],然后再转换为mkString,在cats 或scalaz 中有没有办法在不转换到列表的情况下遍历字符串?

【问题讨论】:

    标签: scala scalaz scala-cats


    【解决方案1】:

    正如@BogdanVakulenko 在他的回答中暗示的那样,String 不是Functor (F[_])。

    cats 中的Traverse 类型类具有以下声明:

    @typeclass trait Traverse[F[_]] extends Functor[F] with Foldable[F] with UnorderedTraverse[F] { self => ... }
    

    你用toListmkString 解决它的方法对我来说很好,但是,如果你想要一个可以工作的普通 Scala 版本:

      def toRnaScala(dna: String): Option[String] = {
        val maybeChars: immutable.Seq[Option[Char]] = dna.map(mMap)
        maybeChars.foldLeft(Option("")) {
          case (acc, Some(c)) => acc.map(_ + c)
          case (_, None) => None
        }
      }
    

    【讨论】:

      【解决方案2】:

      可能是这样的:

      def toRna(dna: String): Option[String] = {
        Some(dna.map(mMap).flatten.mkString)
      }
      

      没有办法直接在字符串上使用遍历,因为字符串是本机 java 结构。在cats/scalaz 中有一个隐式转换,它将遍历方法添加到集合中。此隐式仅适用于具有一个类型参数((* -> *)或​​F[_])的类型。 String 只是一个 T,所以 scala 不能应用这种隐式转换。

      implicit def toTraverseOps[F[_], C](target : F[C])
                  (implicit tc : cats.Traverse[F]) : Traverse.Ops[F, C]
      

      【讨论】:

      • 此实现将简单地忽略所有不是 'A'、'T'、'G'、'C' 的字符,而不是使用 None 失败。
      猜你喜欢
      • 2021-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-18
      • 2018-05-15
      相关资源
      最近更新 更多