如何使用scala来掌握单体的概念和结构

157 阅读3分钟

概述

在这篇文章中,我将努力保持一切对初学者友好,但你仍然需要对Scala有一些基本的了解,这将有助于你的工作。在这篇文章中,我们会经常使用纯函数、副作用等术语,所以请确保你对这些术语有一定的了解。

单体?

单体结构执行连续的计算,它是一个涵盖另一个对象的对象。这里我们可以说,一个计算的输出可以作为其他计算的输入。单体更是一种概念或做事的方式。因此,像List、Sequence等在Scala中支持map和flat map的集合也被认为是Monadic。

例子

val aSeq = Seq("Hello", "world")

这里的 "aList "只是一个简单的列表,我们将尝试对其使用map()函数,其结果是这样的

val upperCaseMap = aSeq.map(_.toUpperCase())

如果你试图打印upperCaseMap的值,它会看起来像这样。List(HELLO, WORLD)

现在,让我们尝试用一个平面地图做同样的事情。

val upperCaseFlatMap = aSeq.flatMap(x => x.toUpperCase()) 

现在,当我们试图打印 upperCaseFlatMap 函数时,输出结果看起来像这样。

List(H, E, L, L, O, W, O, R, L, D)。所以,如果你注意到flat map在应用于seq的时候,会返回一个去除内部分组的列表。

单体的用例

假设我们需要做一个防止多线程访问一个值的类,所以让我们做一个名为 "SafeValue "的案例类,我们将使它成为通用的,比如类型为'T'和协变的,让我们包裹一个内部值,比如类型为'T'的 "内部值"。

object MonadForBeginners extends App {

  case class SafeValue[+T](private val internalValue: T){
    def get: T = synchronized {
      internalValue
    }
  }

  def safeValueTrigger[T](value: T): SafeValue[T] = SafeValue(value)

  val input = safeValueTrigger("Hello Safe Value")
  // Extract
  val inputString = input.get
  // Transform
  val upperString = inputString.toUpperCase()
  // Wrap
  val upperSafeInputString = SafeValue(upperString)
}

为了使事情变得更简单,我们可以在我们的案例类中制作另一个函数,这样它就可以为我做所有的事情,即提取、转换和包装,一气呵成。所以这就是它的样子。

object MonadForBeginners extends App {

  case class SafeValue[+T](private val internalValue: T){
    def get: T = synchronized {
      internalValue
    }

    def transformer[S](transform: T => SafeValue[S]): SafeValue[S] = synchronized{
      transform(internalValue)
    }
  }

  def safeValueTrigger[T](value: T): SafeValue[T] = SafeValue(value)

  val input = safeValueTrigger("Hello Safe Value")
  // Extract
  val inputString = input.get
  // Transform
  val upperString = inputString.toUpperCase()
  // Wrap
  val upperSafeInputString = SafeValue(upperString)

  // Compressed Form
  val upperBetterSafeInputString = input.transformer(s => SafeValue(s.toUpperCase()))

}

现在我们可以摆脱我们的提取、转换和包装了。这就是我们为单体创造了一个条件的地方。

object MonadForBeginners extends App {

  case class SafeValue[+T](private val internalValue: T){
    def get: T = synchronized {
      internalValue
    }

    def transformer[S](transform: T => SafeValue[S]): SafeValue[S] = synchronized{
      transform(internalValue)
    }
  }

  def safeValueTrigger[T](value: T): SafeValue[T] = SafeValue(value)

  val input = safeValueTrigger("Hello Safe Value")

  val upperBetterSafeInputString = input.transformer(s => SafeValue(s.toUpperCase()))
  
}

那么到底什么是单体呢?

你可以说单体有2个基本的行为,首先,单体可以将一些比方说类型为'T'的值包装成另一个也许更有趣的值 "在我们的例子中是SafeValue"。其次,能够将这个有趣的值转化为其他有趣的值。

总结

这篇文章谈论了单体的概念和它的结构。如何使用scala来掌握它。