如何让 do 块提前返回?

2024-05-25

我正在尝试使用 Haskell 抓取网页并将结果编译到一个对象中。

如果出于某种原因,我无法从页面获取所有项目,我想停止尝试处理页面并提前返回。

例如:

scrapePage :: String -> IO ()
scrapePage url = do
  doc <- fromUrl url
  title <- liftM headMay $ runX $ doc >>> css "head.title" >>> getText
  when (isNothing title) (return ())
  date <- liftM headMay $ runX $ doc >>> css "span.dateTime" ! "data-utc"
  when (isNothing date) (return ())
  -- etc
  -- make page object and send it to db
  return ()

问题是when不会停止 do 块或阻止其他部分的执行。

这样做的正确方法是什么?


return在 haskell 中不做同样的事情return在其他语言中。相反,什么return所做的是将一个值注入到一个 monad 中(在本例中IO)。你有几个选择

最简单的是使用 if

scrapePage :: String -> IO ()
scrapePage url = do
  doc <- fromUrl url
  title <- liftM headMay $ runX $ doc >>> css "head.title" >>> getText
  if (isNothing title) then return () else do
   date <- liftM headMay $ runX $ doc >>> css "span.dateTime" ! "data-utc"
   if (isNothing date) then return () else do
     -- etc
     -- make page object and send it to db
     return ()

另一种选择是使用unless

scrapePage url = do
  doc <- fromUrl url
  title <- liftM headMay $ runX $ doc >>> css "head.title" >>> getText
  unless (isNothing title) do
    date <- liftM headMay $ runX $ doc >>> css "span.dateTime" ! "data-utc"
    unless (isNothing date) do
      -- etc
      -- make page object and send it to db
      return ()

这里的普遍问题是IOmonad 没有控制作用(例外情况除外)。另一方面,你可以使用 Maybe monad 变压器

scrapePage url = liftM (maybe () id) . runMaybeT $ do
  doc <- liftIO $ fromUrl url
  title <- liftIO $ liftM headMay $ runX $ doc >>> css "head.title" >>> getText
  guard (isJust title)
  date <- liftIO $ liftM headMay $ runX $ doc >>> css "span.dateTime" ! "data-utc"
  guard (isJust date)
  -- etc
  -- make page object and send it to db
  return ()

如果你真的想获得全面的控制效果,你需要使用ContT

scrapePage :: String -> IO ()
scrapePage url = runContT return $ do
  doc <- fromUrl url
  title <- liftM headMay $ runX $ doc >>> css "head.title" >>> getText
  when (isNothing title) $ callCC ($ ())
  date <- liftM headMay $ runX $ doc >>> css "span.dateTime" ! "data-utc"
  when (isNothing date) $ callCC ($ ())
  -- etc
  -- make page object and send it to db
  return ()

警告:以上代码均未经过测试,甚至没有进行类型检查!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何让 do 块提前返回? 的相关文章

  • 为什么 GeneralizedNewtypeDeriving 没有安全的 Haskell?

    来自 GHC 手册 第安全语言 http www haskell org ghc docs 7 6 2 html users guide safe haskell html safe language 模块边界控制 使用安全语言编译的 Ha
  • 计算/获取分层数据的“级别”

    好吧 我真的不知道这是否是正确的标题 但我不知道如何称呼它 我的问题是关于我的作业 我现在已经工作了几个小时 主题是 函数式数据结构 我有点陷入困境 我不知道如何继续 所以我需要编写一个具有以下签名的函数 data Heap e t Hea
  • 副作用是纯函数中找不到的一切吗?

    可以肯定地说 以下二分法成立 每个给定的函数是 要么纯粹 或有副作用 如果是这样 函数的 副作用就是纯函数中找不到的任何东西 这很大程度上取决于您选择的定义 可以公平地说 函数是pure or impure 纯函数始终返回相同的结果并且不会
  • 如何在 blaze-html 中渲染 blaze-svg 标记

    我想将使用 blaze svg 生成的 svg 图直接包含在使用 blaze html 生成的 html 中 两者都基于 blaze markup 所以我希望它很容易 diagram1 Svg diagram1 try1 Html try1
  • 如何向 Scotty 中间件添加基本身份验证?

    我目前正在制作 Scotty API 但找不到任何 basicAuth 实现的示例 Wai Middleware HttpAuth 具体来说 我想将基本身份验证标头 用户 通行证 添加到我的某些端点 即以 admin 开头的端点 我已经设置
  • 如何在 Haskell 中枚举递归数据类型?

    这篇博文 http lukepalmer wordpress com 2008 05 02 enumerating a context free language 对于如何使用 Omega monad 对角枚举任意语法有一个有趣的解释 他提
  • 如何在 TH 拼接中复制 'name 的行为

    考虑这个 Haskell 文件 LANGUAGE TemplateHaskell OPTIONS GHC fplugin Test Inspection Plugin module Text main where import Test I
  • 'lens' 的阴谋集团依赖性解析失败

    我刚刚做了一个阴谋更新并尝试从 hackage 安装 lens 这给了我以下错误 cabal install j lens Resolving dependencies Configuring dlist 0 7 0 1
  • 如何获取常量内存中的统计数据

    我有一个函数 它会创建一些随机的数值结果 我知道 结果将是 a 小 a b 约 50 范围内的整数a b 我想创建一个执行上述函数 1000000 次的函数 并计算每个结果出现的频率 该函数使用随机生成器来生成结果 问题是 我不知道如何在常
  • “反向”使用 Maybe Monad

    假设我有很多功能 f a gt Maybe a g a gt Maybe a h a gt Maybe a 我想按以下方式组合它们 如果 f 返回 Nothing 则计算 g 如果 g 返回 Nothing 则计算 h 如果其中任何一个计算
  • 使用 PHP 和 xpath 中的抓取功能提取 HTML 页面中的字符串

    我需要抓取这个 HTML 页面 https www sanita puglia it monitorpo aslfg monitorps web monitorps monitorPSperASL do codNazionale 16011
  • 如何找到仅是 2、3 和 5 的幂的倍数的所有数字的列表? [复制]

    这个问题在这里已经有答案了 I am trying to generate a list of all multiples which can be represented by the form where a b and c are w
  • Haskell 测量函数性能

    在 Haskell 中 我如何 简单地 测量函数的性能 例如 运行需要多长时间 或者需要多少内存 我知道分析 但是 是否有一种更简单的方法不需要我对代码进行太多更改 测量运行需要多长时间以及需要多少内存是两个独立的问题 即 基准测试和分析
  • 从网站上的表格中抓取数据,而无需搜索标签

    这是这个问题的延续使用 InStr 搜索引号 空格 冒号等 https stackoverflow com questions 52673819 using instr to search for quotes spaces colons
  • Jsoup - 获取仅包含指定属性及其值的 HTML 标记

    我想用jsoup从页面中提取具有以下内容的元素only一些特定的属性和值 我已经经历过以下提到的方法 但没有一个很好地解决了我的目的 Jsoup s getElementsByAttributesMatching 选择查询的这种格式 doc
  • 使用 VBA 的下拉菜单

    我需要使用 VBA 从下拉菜单中选择特定选项 我怎样才能做到这一点 链接到我们试图从中提取的网页 IE document getElementsByName down count click 我尝试过的代码 Full Module Priv
  • 什么是阴谋地狱?

    在阅读有关 阴谋地狱 的内容时 我有点困惑 因为这个词的含义太多了 我猜最初 Cabal Hell 指的是钻石依赖问题 该问题是通过限制构建计划在每个构建计划中只有任何包的单个版本来解决的 一个包的两个不同版本不能存在于单个构建计划中 正如
  • Haskell 和 Idris 之间的区别:类型宇宙中运行时/编译时的反映

    因此 在 Idris 中 编写以下内容是完全有效的 item b Bool gt if b then Nat else List Nat item True 42 item False 1 2 3 cf https www youtube
  • Haskell 中的类型化抽象语法和 DSL 设计

    我正在 Haskell 中设计 DSL 我想要进行赋值操作 像这样的东西 下面的代码只是为了在有限的上下文中解释我的问题 我没有类型检查 Stmt 类型 data Stmt forall a Assign String Exp a Assi
  • 使用 Haskell 将函数注入到 Java .class 文件中

    我使用 Haskell 编写了一个 Java 字节码解析器 它工作得很好 然而下一步让我完全难住了 我的 Haskell 程序需要修改 class 文件 以便在执行时 Java 程序打印 输入 此处的方法名称 在执行方法之前 并且 退出 此

随机推荐

  • MS Office SaveAs 类型 FileDialog 在 vb 中带有过滤器

    我想创建一个带有过滤器的 另存为 文件对话框 但这似乎无法使用 FileDialog 类 Microsoft Office 12 0 对象库 实现 文档实际上提到了这一点here http msdn microsoft com en us
  • 通过 MVC 将数据写入数据库的最佳方法是什么?

    我正在使用 MVC 和 EF Core 开发一个家庭作业项目 我正在寻找将数据写入数据库的最佳方法 我是初学者 有两张桌子 Predbilje ba 报名 和Seminari 研讨会 public class Predbilje ba Ke
  • 向窗口句柄发送消息

    我尝试使用 sendmessage 将消息从我的 C 应用程序传递到 C 我的c 代码是这样的 int tmain int argc TCHAR argv COPYDATASTRUCT cpd cpd dwData 0 LPCWSTR st
  • 在 Jest 测试中使用 webpack 的工作加载器解析导入

    我正在编写一个 Jest 测试 但在解决此使用 webpack 的导入时遇到问题worker loader import ImageInfoWorker from worker loader name image info WORKERS
  • Gitlab CI服务端口是如何暴露的?

    我有一个 gitlab ci yml file integration test services name registry gitlab com group project testmailserver 1 1 alias mail e
  • 在大画布上滚动

    我需要一些帮助来了解滚动绘制到 Android 画布上的项目的基础知识 假设我想创建一个时间线 其中 0 处的时间是可视化的顶部 并且随着时间的增加 时间线继续呈现在上一个点下方 如果我想在 Android 上渲染它 我知道我可以通过重写
  • 如何在 C# 中停止程序进一步执行

    string FirstName Console ReadLine if FirstName Length gt 12 Console WriteLine if FirstName Length lt 3 Console WriteLine
  • mutate rowSums 排除一列

    我有一个像这样的数据框 gt df Source local data frame 4 x 4 a x y z 1 name1 1 1 1 2 name2 1 1 1 3 name3 1 1 1 4 name4 1 1 1 想要通过添加 x
  • 为什么 NSOrderedSet 不继承 NSSet?

    当然 有序集是集合的更具体的情况 那么为什么NSOrderedSet继承自NSObject而不是NSSet 我通过了界面NSSet你是对的 有序集似乎满足里氏替换原则 http en wikipedia org wiki Liskov su
  • 有没有办法防止 Spring Boot 覆盖 bean?

    与春天的抽象可刷新应用程序上下文 http docs spring io spring docs current javadoc api org springframework context support AbstractRefresh
  • 使用 Spark SQL 时找不到 Spark Logging 类

    我正在尝试用 Java 进行简单的 Spark SQL 编程 在程序中 我从 Cassandra 表获取数据 将RDD into a Dataset并显示数据 当我运行spark submit命令 我收到错误 java lang Class
  • 获取 PHAsset 的本地文件路径

    我希望我的用户能够在 Instagram 上分享一张照片 并且我需要获取该照片的本地文件目录 不过 我将图像作为 PHAsset 获取 而不是 ALAsset 所有其他答案似乎都涵盖了这个主题 查看 PHAsset 文档 我没有看到 本地目
  • 未捕获的 InvalidValueError:setMap:不是 Map 的实例

    当我使用sencha touch2 2 1时 我遇到了一个问题 在查看器中 items id mapCanvas xtype map useCurrentLocation true 在控制器中 var map Ext getCmp mapC
  • 未找到 GroovyEvaluator

    我会尝试在以下位置制作我的 PIE 3D 报告iReport 在我的 struts xml 中 我用这个来调用我的报告
  • 如何使用JSqlParser向sql添加where条件?

    我想用JSqlParser向sql添加where条件 例如 Before select from test table where a 1 group by c After select from test table where a 1
  • 从 TFS 下载工作项附件(文件已损坏)

    我正在尝试创建 C 代码 因此我可以自动从 Team Foundation Server 下载 BUGS 预定义查询的所有附件 该代码似乎工作得很好 但所有下载的文件都因意外原因而损坏 我无法查看它们 有人可以看一下代码并分享意见吗 非常感
  • PHP 7.4 已弃用 get_magic_quotes_gpc 函数替代

    我遇到了我的旧代码之一正在使用的情况get magic quotes gpc 最新版本已弃用PHP 版本 7 4 目前 我有这样的事情 添加斜杠 return get magic quotes gpc addslashes string s
  • GIT:向非当前分支添加本地更改

    我通常会遇到这样的情况 我做了一些本地更改 却发现我在错误的分支上进行了更改 因此我需要在提交之前切换分支 问题是当有本地更改时我无法切换分支 有办法做到这一点吗 显然 我可以复制更新的文件 切换分支 然后将它们复制回来 但这看起来并不聪明
  • 没有路线匹配 [GET]“user/sign_out”rails 5

    我目前使用 Devise 遇到此错误 并且我已经尝试了其他问题中的多种方法 以便以零运气解决它 首先建议我确保将该方法添加为删除 No luck 然后我被建议我需要在我的布局标题中包含以下内容 or this 还是 运气不好 最后 建议我更
  • 如何让 do 块提前返回?

    我正在尝试使用 Haskell 抓取网页并将结果编译到一个对象中 如果出于某种原因 我无法从页面获取所有项目 我想停止尝试处理页面并提前返回 例如 scrapePage String gt IO scrapePage url do doc