haskell词搜索程序开发

时间:2011-05-31 13:56:40

标签: function haskell recursion ghci

你好我正在做一些单词搜索程序

例如

当“text.txt”文件包含“foo foos foor fo ... foo fool”时

并搜索“foo”

然后只打印2号

并反复搜索

但我是haskell初学者

我的代码在这里

:module +Text.Regex.Posix
putStrLn "type text file"
filepath <- getLine
data <- readFile filepath

--1. this makes <interactive>:1:1: parse error on input `data' how to fix it?

parsedData =~ "[^- \".,\n]+" :: [[String]]

--2. I want to make function and call it again and again
searchingFunc = do putStrLn "search for ..."
        search <- getLine
        result <- map (\each -> if each == search then count = count + 1) data
        putStrLn result
        searchingFunc
}

抱歉非常糟糕的代码

我的开发环境是Windows XP SP3 WinGhci 1.0.2

几小时前我开始使用haskell对不起

非常感谢你阅读!

编辑:这是原始方案代码

谢谢!

#lang scheme/gui
(define count 0)
(define (search str)
  (set! count 0)
  (map (λ (each) (when (equal? str each) (set! count (+ count 1)))) data)
  (send msg set-label (format "~a Found" count)))   

(define path (get-file))
(define port (open-input-file path))
(define data '())
(define (loop [line (read-line port)]) 
  (when (not (eof-object? line))
    (set! data (append data 
                       (regexp-match* #rx"[^- \".,\n]+" line)))
    (loop)))
(loop)
(define (cb-txt t e) (search (send t get-value)))
(define f (new frame% (label "text search") (min-width 300)))
(define txt (new text-field% (label "type here to search") (parent f) (callback (λ (t e) (cb-txt t e)))))
(define msg (new message% (label "0Found           ") (parent f)))
(send f show #t)

3 个答案:

答案 0 :(得分:4)

我应该首先迭代每个人(并且应该)说的话:从像Real World Haskell这样的书开始!也就是说,我将发布一个编译代码的快速演练,并希望能够做到与您最初的预期相近的内容。评论是内联的,希望能够说明您的方法的一些缺点。

import Text.Regex.Posix                                                               

-- Let's start by wrapping your first attempt into a 'Monadic Action'
-- IO is a monad, and hence we can sequence 'actions' (read as: functions)
-- together using do-notation.                                                                 
attemptOne :: IO [[String]]
-- ^ type declaration of the function 'attemptOne'
-- read as: function returning value having type 'IO [[String]]'                                                            
attemptOne = do                                                                        
  putStrLn "type text file"                                                            
  filePath <- getLine                                                                  
  fileData <- readFile filePath                                                        
  putStrLn fileData                                                                    

  let parsed = fileData =~ "[^- \".,\n]+" :: [[String]]
  -- ^ this form of let syntax allows us to declare that
  -- 'wherever there is a use of the left-hand-side, we can
  -- substitute it for the right-hand-side and get equivalent
  -- results.                            
  putStrLn ("The data after running the regex: " ++ concatMap concat parsed)           

  return parsed                                      
  -- ^ return is a monadic action that 'lifts' a value
  -- into the encapsulating monad (in this case, the 'IO' Monad).                                  

-- Here we show that given a search term (a String), and a body of text to             
-- search in, we can return the frequency of occurrence of the term within the         
-- text.                                                                               
searchingFunc :: String -> [String] -> Int                                             
searchingFunc term                                                                     
    = length . filter predicate                                                        
  where                                                                                
    predicate = (==)term                                                               
  -- ^ we use function composition (.) to create a new function from two               
  -- existing ones:                                                                    
  --   filter (drop any elements of a list that don't satisfy                          
  --           our predicate)                                                          
  --   length: return the size of the list                                             

-- Here we build a wrapper-function that allows us to run our 'pure'            
-- searchingFunc on an input of the form returned by 'attemptOne'.                                                                 
runSearchingFunc :: String -> [[String]] -> [Int]                                      
runSearchingFunc term parsedData                                                       
  = map (searchingFunc term) parsedData                                                

-- Here's an example of piecing everything together with IO actions                    
main :: IO ()                                                                          
main = do                                                                              
  results <- attemptOne                                                                
  -- ^ run our attemptOne function (representing IO actions)                           
  -- and save the result                                                               
  let searchResults = runSearchingFunc "foo" results                                   
  -- ^ us a 'let' binding to state that searchResults is                               
  -- equivalent to running 'runSearchingFunc'                                          
  print searchResults                                                                  
  -- ^ run the IO action that prints searchResults                                     
  print (runSearchingFunc "foo" results)                                               
  -- ^ run the IO action that prints the 'definition'                                  
  -- of 'searchResults'; i.e. the above two IO actions                                 
  -- are equivalent.                                                                   
  return ()
  -- as before, lift a value into the encapsulating Monad;
  -- this time, we're lifting a value corresponding to 'null/void'.

要加载此代码,请将其保存到.hs文件中(我将其保存到“temp.hs”中),然后从ghci运行以下命令。注意:文件'f'包含几个输入字:

*Main Text.Regex.Posix> :l temp.hs                               
[1 of 1] Compiling Main             ( temp.hs, interpreted )     
Ok, modules loaded: Main.                                        
*Main Text.Regex.Posix> main                                     
type text file                                                   
f                                                                
foo foos foor fo foo foo                                         

The data after running the regex: foofoosfoorfofoofoo            
[1,0,0,0,1,1]                                                    
[1,0,0,0,1,1]                                                    

这里有很多东西,从符号到Monadic动作,'let'绑定纯粹和不纯的函数/值之间的区别。我不能强调从好书中学习基础知识的价值!

答案 1 :(得分:2)

请一步一步开始。 Haskell中的IO是 hard ,所以你不应该从文件操作开始。我建议编写一个在给定String上正常工作的函数。这样你就可以学习语法,模式匹配,列表操作(地图,折叠)和递归,而不会被do符号分散注意力(哪种看起来命令,但不是,真的需要更深入的了解。)

您应该查看Learn you a HaskellReal World Haskell以获得良好的基础。你现在所做的只是在黑暗中磕磕绊绊 - 如果你学习的语言类似于你所知道的语言,可以工作,但绝对不适合Haskell。

答案 2 :(得分:2)

这是我用它做的。它没有进行任何错误检查,并且尽可能基本。

import Text.Regex.Posix ((=~))
import Control.Monad (when)
import Text.Printf (printf)

-- Calculates the number of matching words
matchWord :: String -> String -> Int
matchWord file word = length . filter (== word) . concat $ file =~ "[^- \".,\n]+"

getInputFile :: IO String
getInputFile = do putStrLn "Enter the file to search through:"
                  path <- getLine
                  readFile path -- Attention! No error checking here

repl :: String -> IO ()
repl file = do putStrLn "Enter word to search for (empty for exit):"
               word <- getLine
               when (word /= "") $
                 do print $ matchWord file word
                    repl file

main :: IO ()
main = do file <- getInputFile
          repl file