如何插入此类型的孔3 [英] How to plug this type hole 3

查看:58
本文介绍了如何插入此类型的孔3的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

接着我的最后一个问题,我现在可以得到我想要的结果,但是以一种完全邪恶的方式:使用unsafePerformIO.我知道这不是解决此问题的正确方法(尽管为了防御,我还是从笨拙的检查类型中得到了这个主意,然后从kmett的回购中进行ag搜索,以了解他何时在100个左右的回购中使用了unsafePerformIO.阅读有关骇客的警告,我知道这很糟糕.)

Following on from my last question, I am now able to get the desired result I was after, but in a totally evil way: using unsafePerformIO. I understand this is not the right way to approach this (though to my defense I got the idea from hoogle checking types, and then from an ag search in kmett's repos to see when he used unsafePerformIO across a hundred or so repos. I read the warnings on hackage, I know it is bad.).

我现在想要的是在没有unsafePerformIO的情况下执行此操作的方法.

What I'd like now is to be a way to do this without 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视频,但是直到那时.预先感谢!

Along the way I tried to use hole typing and lots of Hoogle to get help from the tools (teach a man to fish..). I need mentoring to get the process of discovery using tools and docs more dialed. If you have tips on how you approach such things, or at least imagine what you would do if you lost all your long term memory of Haskell except hole typing and hoogle and let me know how you would proceed. I plan to watch Brian McKenna's data61 videos soon, but until then. Thanks in advance!

推荐答案

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

First, let's split out your filtering function:

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

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

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

Now, use some syntactic sugar to clean up main:

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

下一步,更改isAnnotatedPdf以在IO内部返回其结果,然后修改main以便可以执行以下操作:

Next, change isAnnotatedPdf to return its result inside of IO, and then modify main so that it's okay to do that:

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

isAnnotatedPdf中提取变量pdfTitle,以使下一步更加清晰:

Extract a variable pdfTitle inside isAnnotatedPdf to make the next step more clear:

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

最后,将isAnnotatedPdf更改为使用其新的IO上下文,而不使用您的unsafePerformIO包装器:

Finally, change isAnnotatedPdf to use its new IO context instead of using your unsafePerformIO wrapper:

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

您完成了!现在,您可以摆脱titleString和对unsafePerformIO的所有引用.

And you're done! Now you can get rid of titleString and all of your references to unsafePerformIO.

作为奖励,您现在可以通过将纯takeExtension检查移至单子标题检查之前,轻松地避免对非PDF内容调用pdfInfo的情况,如下所示:

As a bonus, you can now easily avoid the need to call pdfInfo on things that aren't PDFs, by moving the pure takeExtension check to before the monadic title check, like this:

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

这篇关于如何插入此类型的孔3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆