如何堵住此类孔 3

2024-01-12

继从我的最后一个问题 https://stackoverflow.com/questions/58035216/how-to-plug-this-type-hole-2,我现在能够得到我想要的结果,但以一种完全邪恶的方式:使用unsafePerformIO。我知道这不是解决这个问题的正确方法(尽管为了我的辩护,我从 hoogle 检查类型中得到了这个想法,然后从 kmett 的存储库中的 ag 搜索中查看他何时使用unsafePerformIO跨越一百个左右的存储库。我阅读了有关黑客攻击的警告,我知道这很糟糕。)。

我现在想要的是一种无需unsafePerformIO.

这是代码:

module Main where

import Control.Monad (liftM)
import Data.List (isSubsequenceOf)
import qualified Data.Text as T
import System.Directory (listDirectory)
import System.FilePath ((</>), takeExtension)
import System.IO.Unsafe (unsafePerformIO)
import Text.PDF.Info

title :: FilePath -> IO String
title path = do
  result <- pdfInfo path
  case result of
    Left someError -> do
      return "no title"
    Right info -> do
      case (pdfInfoTitle info) of
        Nothing -> return "no title"
        Just title -> return (T.unpack title)

titleString :: FilePath -> String
titleString s = unsafePerformIO (title s)
{-# NOINLINE titleString #-}

dir = "/some/path"

main :: IO ()
main = do
  print =<<
    liftM
      (filter
         (\path ->
            (isSubsequenceOf "annotated" (titleString (dir </> path))) &&
            (takeExtension path == ".pdf")))
      (listDirectory dir)

一路上,我尝试使用洞打字和大量的 Hoogle 从工具中获得帮助(授人以渔......)。我需要指导来更好地使用工具和文档进行发现过程。如果你有关于如何处理这些事情的提示,或者至少想象一下,如果你失去了除了洞打字和胡歌之外的所有 Haskell 长期记忆,你会做什么,并让我知道你将如何进行。我计划很快观看 Brian McKenna 的 data61 视频,但在那之前。提前致谢!


首先,让我们拆分一下过滤功能:

isAnnotatedPdf :: FilePath -> Bool
isAnnotatedPdf path = (isSubsequenceOf "annotated" (titleString (dir </> path))) && (takeExtension path == ".pdf")

main :: IO ()
main = do
  print =<<
    liftM
      (filter isAnnotatedPdf)
      (listDirectory dir)

现在,使用一些语法糖来清理main:

main :: IO ()
main = do
  dirList <- listDirectory dir
  let filteredList = filter isAnnotatedPdf dirList
  print filteredList

接下来,改变isAnnotatedPdf返回其结果IO,然后修改main这样就可以这样做:

isAnnotatedPdf :: FilePath -> IO Bool
isAnnotatedPdf path = do
  return $ (isSubsequenceOf "annotated" (titleString (dir </> path))) && (takeExtension path == ".pdf")

main :: IO ()
main = do
  dirList <- listDirectory dir
  filteredList <- filterM isAnnotatedPdf dirList
  print filteredList

提取变量pdfTitle inside isAnnotatedPdf为了让下一步更加清晰:

isAnnotatedPdf :: FilePath -> IO Bool
isAnnotatedPdf path = do
  let pdfTitle = titleString (dir </> path)
  return $ (isSubsequenceOf "annotated" pdfTitle) && (takeExtension path == ".pdf")

最后,改变isAnnotatedPdf使用其新的IO上下文而不是使用你的unsafePerformIO包装:

isAnnotatedPdf :: FilePath -> IO Bool
isAnnotatedPdf path = do
  pdfTitle <- title (dir </> path)
  return $ (isSubsequenceOf "annotated" pdfTitle) && (takeExtension path == ".pdf")

你就完成了!现在你可以摆脱titleString以及你所有的参考文献unsafePerformIO.


作为奖励,您现在可以轻松避免致电pdfInfo对于非 PDF 的内容,通过移动纯takeExtension在单子标题检查之前检查,如下所示:

isAnnotatedPdf :: FilePath -> IO Bool
isAnnotatedPdf path = if takeExtension path == ".pdf"
  then do
    pdfTitle <- title (dir </> path)
    return $ isSubsequenceOf "annotated" pdfTitle
  else return False

或者使用<$>代替do:

isAnnotatedPdf :: FilePath -> IO Bool
isAnnotatedPdf path = if takeExtension path == ".pdf"
  then isSubsequenceOf "annotated" <$> title (dir </> path)
  else return False
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何堵住此类孔 3 的相关文章

  • 如何使用 Haskell 中的 thyme 库从 Int 值创建 UTCTime?

    我有年 月 日 小时和分钟值 所有这些都是类型Int 我怎样才能将它们转换为UTCTime or UniversalTime 需要导入以下内容 import Control Lens import Data Thyme Clock impo
  • Haskell,optparse-generic 的未命名命令行参数

    我在用着optparse 通用 https hackage haskell org package optparse generic解析名为的程序的命令行参数example 我有一个带有命名字段的数据类型 记录语法 例如 data Exam
  • 如何从 haskell 中的 IOError 获取 errno?

    我在 haskell 平台上 GHC 6 12 1 作为 apt get 安装在 Debian Squeeze 上 鉴于我需要在与最初引发它的线程不同的线程上使用它 如何从 IOError 中获取底层 errno 我需要这个的原因是因为我正
  • 为什么 Haskell 的默认字符串实现是一个字符链接列表?

    Haskell 默认值的事实String众所周知 实现在速度和内存方面都效率不高 据我所知 lists一般来说 在 Haskell 中实现为单链表 并且适用于大多数小型 简单数据类型 例如Int 这似乎不是一个好主意 但是对于String这
  • Haskell scala 互操作性

    我是 Scala 初学者 来自面向对象范式 在了解 Scala 的函数式编程部分时 我被引导到 Haskell 纯函数式编程语言 探索 SO 问题答案 我发现 Java Haskell 具有互操作性 我很想知道 Scala Haskell
  • 持久 selectList 导致错误“无法将类型‘BaseBackend backend0’与‘SqlBackend’匹配”

    我遇到以下编译错误 Couldn t match type BaseBackend backend0 with SqlBackend arising from a use of runSqlite The type variable bac
  • 如何在 Haskell 中向右或向左移动列表的 1 个元素?

    嗨 我一直在寻找答案 但找不到 假设我们有一个像这样的列表 1 10 4 5 3 我怎样才能将 5 向左移动 使这个列表变成 1 10 5 4 3 我尝试过了swapElementsAt通过找到该元素的索引 但它看起来非常不足 swapEl
  • 在依赖类型的函数式编程语言中,扁平化列表是否更容易?

    在 haskell 中寻找一个可以展平任意深度嵌套列表的函数时 即应用的函数concat递归并在最后一次迭代时停止 使用非嵌套列表 我注意到这需要有一个更灵活的类型系统 因为随着列表深度的变化 输入类型也会变化 确实 有几个 stackov
  • 以下两个 lambda 函数的空间复杂度

    我正在阅读以下内容 https en wikibooks org wiki Haskell Graph reduction https en wikibooks org wiki Haskell Graph reduction 其内容如下
  • Haskell 中的中缀运算符优先级

    对于以下 Haskell 表达式 返回 a gt gt f 应该读作 返回a gt gt f or 返回 a gt gt f 这里的相关规则是什么 规则始终是函数应用程序的优先级高于任何运算符 因此 return a gt gt f 被解析
  • 如何在 Haskell 中漂亮地打印表格?

    我想在 Haskell 中漂亮地打印一个类似表格的数据结构 列列表 例如 Table StrCol strings a bc c IntCol ints 1 30 2 DblCol doubles 2 0 4 5 3 2 应该渲染类似 st
  • 有没有更好的方法将 UTC 时间转换为大纪元时间?

    我想将文件的修改时间设置为从 exif 数据获取的时间 为了从 exif 获取时间 我发现 Graphics Exif getTag Exif gt String gt IO Maybe String 要设置文件修改时间 我发现 Syste
  • QuickCheck是否可以生成任意函数

    我试图为身份编写一个 QuickCheck 测试 f y f y 我最初的计划是编写一个返回函数和整数的任意生成器 具有签名Gen Int gt Int Int 并在prop DollerDoesNothing使用 不使用测试该功能应用程序
  • 这个对自身单位的列表理解是如何工作的?

    在 haskell IRC 频道中有人问 是否有一种简洁的方法来定义一个列表 其中第 n 个条目是之前所有条目的平方和 我认为这听起来像一个有趣的谜题 递归定义无限列表是我真正需要练习的事情之一 所以我启动了 GHCi 并开始尝试递归定义
  • Haskell - lambda 表达式

    我试图了解什么是有用的以及如何在 Haskell 中实际使用 lambda 表达式 我不太明白使用 lambda 表达式相对于定义函数的约定方式有何优势 例如 我通常会执行以下操作 let add x y x y 我可以简单地打电话 add
  • 为什么 ZipList 不是 List 的默认应用实例

    我目前正在学习 Haskell 中的应用程序 如果我没记错的话 列表有两个不同的应用实例 List and ZipList 第二个被定义为包装列表值的新类型 这ZipList应用实例对我来说似乎更直观 这可能是一个愚蠢的问题 但有具体原因吗
  • 在 monad 转换器类型类中使用列表 monad?

    我的目标是创建一个在 ReaderT WriterT 堆栈或 RWS 堆栈中使用列表 monad 的函数 更一般地说 如何在 mtl 类型类 例如 MonadReader MonadWriter 中使用列表 monad 我为什么要尝试这样做
  • 在 Haskell 中合并两个列表

    无法弄清楚如何合并两个列表通过以下方式在哈斯克尔 INPUT 1 2 3 4 5 11 12 13 14 OUTPUT 1 11 2 12 3 13 4 14 5 我想提出一个更懒的合并版本 merge ys ys merge x xs y
  • 管道:多个流消费者

    我编写了一个程序来计算语料库中 NGram 的频率 我已经有一个函数 它消耗一串令牌并生成一个订单的 NGram ngram Monad m gt Int gt Conduit t m t trigrams ngram 3 countFre
  • 我是否需要采取明确的操作来促进与持久数据结构的共享?

    我来自命令式背景 正在尝试实现一个简单的不相交集 并集查找 数据结构 以获得在 Haskell 中创建和修改 持久 数据结构的一些练习 目标是有一个简单的实现 但我也关心效率 我的问题与此相关 首先 我创建了一个按等级并集的不相交集森林实现

随机推荐

  • 无法将用户添加到 Hyper-V 管理员组退出代码 2220

    我将 Windows 10 LTSB 与 Visual Studio 2015 结合使用 启用后Hyper V 我安装了独立的Visual Studio Emulator for Android Hyper V 运行良好 因为可以向其中添加
  • 无法获取资源“https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/3.2.1/gradle-3.2.1.pom”

    我最近开始使用 React Native 但是根据伊朗制裁 gradle 无法构建我的第一个项目 所以我使用了 VPN 也舍餐服务 https shecan ir 但我收到以下错误 我阅读了 React Native 说明并按照它们设置了模
  • 如何清空 Drupal 缓存(无需 Devel)

    如何清空 Drupal 缓存 without开发模块 无需在新节点等中运行一些 PHP 语句 无需进入数据库本身 实际上 您如何指示最终用户清除其缓存 当您以管理员身份登录时 显然 并非该网站的每个用户都有权清除缓存 应该有一个页面 管理
  • 将 FontAwesome 5.x 与 PrimeFaces 6.2+ 结合使用

    我正在检查这个问题 如何将 webjars org 中的 Font Awesome 与 JSF 结合使用 https stackoverflow com q 18891768 811293蚂蚁这个问题 FontAwesome 与 Prime
  • 如何在 HTTP 标头中设置 REMOTE_USER?

    我的 Apache 设置有问题 我安装了一个部分接受外部身份验证的 Web 应用程序 我使用 Apache 来管理对我的应用程序网页的访问 如果身份验证成功 环境变量 REMOTE USER 将设置为用户名 然后 用户名通过 HTTP 标头
  • 是否可以在请求中刷新会话?

    我使用创建一个会话requests Session 由于某种原因 服务器端关闭了此连接 所以我必须重新连接 问题是 这个会话在很多地方都使用 所以我想知道是否可以重建 TCP 连接但保留会话对象 以便我仍然可以使用它 Example s r
  • Google javascript API 库 - 日历手表通知

    我正在尝试使用 JS 客户端库订阅日历事件通知 如下所示 gapi client load calendar v3 function var request gapi client calendar events watch calenda
  • 代码契约[Type]实现接口方法{Interface.Method},因此无法添加要求

    我有以下场景 public interface ISomething void DoStuff public class Something ISomething private readonly ISomethingElse someth
  • ValueTypes会导致GC吗?

    如果我有堆栈分配的值类型 什么会清理它们 GC只是堆吧 If这些值位于堆栈上 然后当当前堆栈帧被 弹出 通过返回的方法 时 这些值将被有效地清理 不会调用任何终结器或类似的东西 但内存会用完这些值将在下次堆栈达到那么高时重用 请注意 值类型
  • 使用 PHP 上传到 S3 的 RequestTimeout

    我在从我们的一台服务器上将文件上传到 S3 时遇到问题 我们使用 S3 来存储备份 所有服务器都运行 Ubuntu 8 04 PHP 5 2 4 和 libcurl 7 18 0 每当我尝试上传文件时 亚马逊都会返回 RequestTime
  • 查找近似重复和伪造的图像

    我正在使用感知哈希技术来查找接近重复和完全重复的图像 该代码非常适合查找完全相同的重复图像 然而 找到近似重复和略有修改的图像似乎很困难 由于它们的哈希值之间的差异分数通常类似于完全不同的随机图像的哈希差异 为了解决这个问题 我尝试将几乎重
  • Mysql 选择一列中具有相同值而另一列中具有不同值的行

    如果有人可以验证我的 SQL 查询 我将非常感激 对于以下数据集 MD5 UserPK CategoryPK ADCDE 1 7 ADCDE 1 4 ADCDE 1 7 dffrf 1 7 dffrf 2 7 dffrf 2 6 dffrf
  • 如何将编译器标志传递给 Rust 中的子包? [复制]

    这个问题在这里已经有答案了 我有板条箱A and B A依赖于取决于B and B有一个名为some feature 我可以建造B通过运行使用货物cargo build features some feature 但是我如何为A我可以选择启
  • 如何在 Perl 中将十六进制字符串转换为数字?

    我最近编写了一个脚本 它解析单个二进制字节月份字段的文本表示 不要问 在摆弄 sprintf 一段时间后 我放弃了并这样做了 our months qw x01 1 x02 2 x03 3 x04 4 x05 5 x06 6 x07 7 x
  • 输出在 REPL 中被 # 符号截断

    我编写了一个按预期工作的函数 但我不明白为什么输出是这样的 功能 datatype prop Atom of string Not of prop And of prop prop Or of prop prop XOR A And Not
  • 复制的变量改变了原来的变量?

    我在 Python 中有一个非常非常奇怪的简单问题 def estExt matriz erro 1 Determinar o vector X das solu es print Matrix after print matriz aux
  • 重新定义;不同的基本类型(typedef struct)

    当结构在不同的文件中定义时 我在尝试使结构正常工作时遇到了一些麻烦 据我所知 错误告诉我该结构被定义了两次不同的时间 我相信也许我可能需要在某个地方使用 extern 我尝试过尝试并在 Google 上寻求帮助 但没有成功 任何帮助将不胜感
  • 在 Windows 10 上通过 DISM 安装 IIS Windows 功能

    根据这个链接 https learn microsoft com en us previous versions windows it pro windows 8 1 and 8 hh824822 v win 10 我要安装 IIS Win
  • SSLHandshakeException:未找到证书路径的信任锚。仅适用于 Android API < 19

    我在设备 安卓SSL它似乎适用于我测试的所有 api gt 19 设备 我在 19 年前如何不断收到 未找到认证路径的信任锚 错误 我已经使用 keytool 创建了密钥库 并且似乎不是问题 因为它在某些设备上工作 这是我的代码 URL u
  • 如何堵住此类孔 3

    继从我的最后一个问题 https stackoverflow com questions 58035216 how to plug this type hole 2 我现在能够得到我想要的结果 但以一种完全邪恶的方式 使用unsafePer