我想要实际实现的是在haskell中编写程序。该程序是一个多线程文本文件搜索引擎,它将文本文件分成行列表。每行必须使用模块 Data.List 中的函数 isInfixOf ,该函数应放在模块 Control中的 withAsync 函数内。 Concurrent.Async 。如果在文件中找到我想要搜索的单词,则结果将为True。
我知道以下代码不正确但我正走在正确的道路上。我希望有人为我解决这个问题:
import System.Directory
import Control.Concurrent
import System.FilePath
import Control.Concurrent.Async
import System.Environment
import Data.List hiding (find)
import Control.Monad
import Control.Exception
loop [] = return Nothing
loop (a:as) = do -- <4>
r <- wait a
case r of
Nothing -> loop as
Just a -> return (Just a)
main = do
let lines =readFile ("myfile.txt")
let keyword="to_be_found"
let asyncs=[]
forM lines $ \line -> do
asyncs <- async (print $ isInfixOf keyword line) ++ asyncs
loop asyncs
答案 0 :(得分:1)
忘记IO
一分钟,而您可能认为do
符号与IO
有关,这是一种常见的误解。 IO
只是一个单子,允许你描述与现实世界有关的行为。了解monad是目前的重要部分。
简而言之,monads定义了顺序组合,或者&#34;这样做,然后是#34;,由(>>=) :: Monad m => m a -> (a -> m b) -> m b
证明。在命令式语言中,IO
内的所有内容和>>=
内的所有内容都与;
相同。 Read up on how monads and bind (>>=
) works.
具体而言,您希望在fold
操作列表上async
进行提前终止。
确保您理解asyncContainsPrefix
,因为fileContainsPrefix
是微不足道的部分。实质上,joinAsync False (\r -> if r then pure True else Nothing)
是any
的短路和并发版本。该函数的另一部分是关于描述async
计算。
我有以下工作......它使用pointfree样式的Haskell并且(几乎)eta-reduced形式:
import Data.List (isInfixOf)
import Control.Monad (forM, mapM_, liftM2)
import Control.Concurrent.Async
import Test.QuickCheck
import Test.QuickCheck.Monadic (monadicIO, run)
main :: IO ()
main = do
contains <- fileContainsPrefix "to_be_found" "myfile.txt"
putStrLn $ if contains then "yes" else "no"
--------------------------------------------------------------------------------
-- API:
--------------------------------------------------------------------------------
fileContainsPrefix :: FilePath -> String -> IO Bool
fileContainsPrefix file prefix = lines <$> readFile file >>=
asyncContainsPrefix prefix
asyncContainsPrefix :: Eq a => [a] -> [[a]] -> IO Bool
asyncContainsPrefix prefix ls =
forM ls (async . pure . isInfixOf prefix)
>>= joinAsync False (\r -> if r then pure True else Nothing)
joinAsync :: b -> (a -> Maybe b) -> [Async a] -> IO b
joinAsync z handler [] = pure z
joinAsync z handler (a:as) =
handler <$> wait a >>=
maybe (joinAsync z handler as) ((mapM_ cancel as >>) . pure)
--------------------------------------------------------------------------------
-- Tests:
--------------------------------------------------------------------------------
prop_async_seq :: Eq a => [a] -> [[a]] -> Property
prop_async_seq prefix ls = monadicIO $
liftM2 (==) (pure $ containsPrefix prefix ls)
(run $ asyncContainsPrefix prefix ls)
containsPrefix :: Eq a => [a] -> [[a]] -> Bool
containsPrefix = any . isInfixOf
$ ghci Mult.hs
GHCi, version 7.10.2: http://www.haskell.org/ghc/ :? for help
[1 of 1] Compiling Main ( Mult.hs, interpreted )
Ok, modules loaded: Main.
λ> quickCheck prop_async_seq
+++ OK, passed 100 tests.
答案 1 :(得分:0)
我不知道你是如何顺序阅读文件的每一行的。但是这里有一个函数来确定文件是否包含具有给定前缀的行:
containsPrefix :: FilePath -> String -> IO Bool
filePath `containsPrefix` prefix
= any (isInfixOf prefix) . lines <$> readFile filePath
免责声明:文件将按顺序读取。