разработка программы поиска слова на языке haskell - PullRequest
1 голос
/ 31 мая 2011

привет Я создаю некоторую программу для поиска слов

, например

, когда файл "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 ]

4 голосов
/ 31 мая 2011

Я должен начать с итерации того, что все (и должны) сказать: начните с такой книги, как 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]                                                    

Здесь происходит многое: от нотации до монадических действий, привязок «позвольте» к различию между чистыми и нечистыми функциями / ценностями. Я не могу не подчеркнуть ценность изучения основ из хорошей книги!

2 голосов
/ 31 мая 2011

Вот что я из этого сделал.Он не выполняет проверку ошибок и является максимально простым.

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
2 голосов
/ 31 мая 2011

Пожалуйста, начните шаг за шагом.IO в Haskell - hard , поэтому не стоит начинать с манипулирования файлами.Я бы посоветовал написать функцию, которая правильно работает на данном String.Таким образом, вы можете узнать о синтаксисе, сопоставлении с образцом, манипулировании списками (карты, сгибы) и рекурсии, не отвлекаясь на нотацию do (которая вроде выглядит императивной, но это не так, и действительно нуждается вболее глубокое понимание).

Вы должны проверить Научите вас Haskell или Real World Haskell , чтобы получить прочную основу.То, что вы делаете сейчас, это просто спотыкаетесь в темноте - что может сработать, если вы изучаете языки, которые похожи на те, которые вы знаете, но определенно не для Haskell.

...