概述
在这篇文章中,我将努力保持一切对初学者友好,但你仍然需要对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来掌握它。