1

こんにちは私はいくつかの単語検索プログラムを作っています

例えば

「text.txt」ファイルに「foofoosfoorfo..foofool」が含まれている場合

「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
}

非常に貧弱なコードでごめんなさい

私の開発環境はWindowsXPSP3WinGhci1.0.2です。

数時間前にハスケルを始めましたごめんなさい

読んでくれてありがとう!

編集:これが元のスキームコードです

ありがとう!

#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)
4

3 に答える 3

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]                                                    

ここでは、do 記法からモナド アクション、'let' バインディング、純粋な関数/値と純粋でない関数/値の区別まで、多くのことが行われています。良い本から基礎を学ぶことの価値はいくら強調してもしすぎることはありません!

于 2011-05-31T14:47:23.973 に答える
2

ステップバイステップで開始してください。HaskellのIOは難しいので、ファイル操作から始めるべきではありません。特定のに対して適切に機能する関数を作成することをお勧めしますStringdoそうすれば、構文、パターンマッチング、リスト操作(マップ、フォールド)、および再帰について、表記法に気を取られることなく学ぶことができます(これは必須のように見えますが、そうではなく、実際にはより深い理解が必要です)。

健全な基盤を得るために、LearnyouHaskellまたはRealWorldHaskellをチェックする必要があります。あなたが今していることは、暗闇の中でつまずくだけです-あなたが知っている言語に似ている言語を学べばうまくいくかもしれませんが、Haskellにとっては間違いなくそうではありません。

于 2011-05-31T14:32:13.587 に答える
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
于 2011-05-31T14:54:40.530 に答える