gpt4 book ai didi

scala - 状态 monad - 调整仅适用于部分状态的功能?

转载 作者:行者123 更新时间:2023-12-04 17:40:52 24 4
gpt4 key购买 nike

我有一个本质上是一个三元组的一般状态,以及许多函数,每个函数都与该状态的一部分有关。我正在尝试为这些功能制定一组通用适配器,以便我可以在 State monad 管道中使用它们。

这可能完全是错误的。随意提出这种情况。

我提前为 Java 和 pidgin Scala 的混合道歉。我实际上是在用 Java 做这件事作为学习练习,但没有人有时间阅读所有这些。为了讨论,我省略了很多无趣的复杂性;不要担心域建模。

有问题的状态是这样的:

ImportState(row:CsvRow, contact:Contact, result:ImportResult)
ImportResultADD 之一, MERGE , 或 REJECT .

我定义的函数是:
def rowToContact: ImportRow => Contact

def findMergeCandidates: Contact => (Contact, List[Contact])

// merges, or declines to merge, setting the result
def merge: (Contact, List[Contact]) => (Contact, ImportResult)

def persist: Contact => ImportResult

def commitOrRollback: ImportState => ImportState

def notifyListener: ImportState => Nothing

到目前为止我定义的适配器非常简单,并且处理 ImportState 的各个属性。 :
def getRow: ImportState => ImportRow

def getContact: ImportState => Contact

def setRow(f: _ => ImportRow): ImportState => ImportState

def setContact(f: _ => Contact): ImportState => ImportState

def setResult(f: _ => ImportResult): ImportState => ImportState

(损坏的)管道看起来像这样(在 Java 中):
State.<ImportState>init()
.map( setRow( constant(row) ) )
.map( setContact( getRow.andThen(rowToContact) ) )
.map( getContact.andThen(findMergeCandidates).andThen(merge) ) // this is where it falls apart
.map( setResult( getContact.andThen(persist) ) )
// ... lots of further processing of the persisted contact
.map(commitOrRollback)
.map(notifyListener);

眼前的问题是 merge返回一个元组 (Contact, ImportResult) ,我想将其应用于状态的两个属性( contactresult ),同时保留第三个属性 row .

到目前为止,我已经提出了几种适应合并的方法,它们都很糟糕:
  • 定义一些打包和解包元组的函数,并在管道中直接使用它们。此选项非常嘈杂。
  • ImportState 定义一次性适配器和 merge .这个选项感觉就像放弃。

  • 有没有更好的办法?

    最佳答案

    您的问题被标记为 Haskell - 我希望这意味着您可以阅读 Haskell,而不是有人看到了“monads”并添加了它。在这个假设下,我将在这个答案中使用 Haskell,因为这是我现在认为的语言;)

    有一个有用的概念称为“功能镜头”,其中包含几个 Haskell 库实现。核心思想是“镜头”是一对函数:

    data Lens a b = Lens { extract :: (a -> b), update :: (a -> b -> a) }

    这代表了一种获取和更新结构“部分”的功能方式。使用这样的类型,您可以编写一个函数,例如:
    subState :: Lens a b -> State a t -> State b t
    subState lens st = do
    outer <- get
    let (inner, result) = runState st (extract lens outer)
    put (update lens outer inner)
    return result

    将其翻译成 Java 听起来像是一项有趣(并且可能非常具有挑战性)的练习!

    关于scala - 状态 monad - 调整仅适用于部分状态的功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4215875/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com