如何插入此类型的孔3 [英] How to plug this type hole 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屋!