haskell - 在 Monad 链中对重复应用进行抽象

标签 haskell monads higher-order-functions

Haskell wikibook有一个例子展示了如何链接 lookup尝试在整个数据库中查找不同连接信息时的命令,请参见此处:

getTaxOwed :: String       -- their name
       -> Maybe Double -- the amount of tax they owe
getTaxOwed name = 
  lookup name phonebook >>=
    (\number -> lookup number governmentDatabase) >>=
      (\registration -> lookup registration taxDatabase)

并改写为 do符号:
getTaxOwed name = do
  number       <- lookup name phonebook
  registration <- lookup number governmentDatabase
  lookup registration taxDatabase

现在,每当我看到一个函数重复不止一次时,我会立即尝试想办法抽象它的重复应用程序,但因为我还没有使用 Monads在实践中还有很多,因为它们似乎已经处于相当高的抽象级别,我不知道在这种情况下如何处理。

如果有的话,编码人员可以通过哪些方式抽象上述常见模式,即调用 lookup在每一行?

(顺便说一句:这是“抽象结束”一词的合适上下文吗?我觉得它捕获了我的意思,但我不确定,我想确保我作为一个相对较新的编码员适本地使用术语; 我查看了其他帖子,这些帖子阐明了它的用法和含义,但我仍然无法弄清楚这个特定的例子)

最佳答案

非常感谢 Carsten 提供的链接 foldM !感谢他们对这个答案的洞察力。

所以,如果我们使用 foldM ,我们可以编写一个重复执行 lookup 的函数链接到依赖于每个先前结果的多个目录。如果,感谢使用 monads , 在任何时候 lookup找不到当前 key在目录中,它将终止,并返回 Nothing :

lookupALot :: Eq a => a -> [(a,b)] -> Maybe b
lookupALot key directories = foldM lookup key directories

这有表单的输出
  foldM f k1 [d1, d2, ..., dm] -- k == key, d == directory
  ==
  do
    k2 <- f k1 d1
    k3 <- f k2 d2
    ...
    f km dm

这是完全相同的结构
  do
    number       <- lookup name phonebook
    registration <- lookup number governmentDatabase
    lookup registration taxDatabase

因此,一种更紧凑的书写方式 getTaxOwed将是:
getTaxOwed :: String -> Maybe Double
getTaxOwed name = foldM lookup name [phonebook, governmentDatabase, taxDatabase]

哪一种让我大吃一惊!该行代码将找到与某人的 name 相关联的电话号码。 ,然后检查 governmentDatabase与他们的号码 registration ,最后从registration中找到他们的税务信息.但请注意,这仅适用于 [(a,b)] 形式的数据。 ,如 lookupALot 的类型所示.

关于haskell - 在 Monad 链中对重复应用进行抽象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32163806/

相关文章:

java - 是否有类似于 Integer::sum 的乘法?

c - C 中的高阶函数

haskell - 在 Haskell 中乱码

java - 将数据从一种数据结构映射到另一种数据结构

haskell - 如何在 Haskell 中获取小数并将其转换为数字列表?

haskell - 如何在 Haskell 的列表理解中有条件地模式匹配

haskell - 状态 monad 函数得到了吗?

Haskell + SDL,不理解函数/状态用法

haskell - 如何对类函数进行等式约束?

scheme - 使用高阶函数映射的字符串加密