2012-04-24 83 views
0

EDIT:YurasとDave4420のアドバイスに続きました(ありがとう)。私はまだいくつかのエラーがあります。質問が更新されました。これは、コンパイルし、作品ByteStringsへの切り替え

import System.Environment 

getRow :: Int -> String -> String 
getRow n = (!!n) . lines 

getField :: Int -> String -> String 
getField n = (!!n) . words' 

words' :: String -> [String] 
words' str = case str of 
         [] -> [] 
         _ -> (takeHead " ; " str) : (words' (takeTail " ; " str)) 

takeHead :: String -> String -> String 
takeHead st1 st2 = case st2 of 
           [] -> [] 
           _ -> if st1 == (nHead (length st1) st2) then [] else (head st2):(takeHead st1 (tail st2)) 

takeTail :: String -> String -> String 
takeTail st1 st2 = case st2 of 
           [] -> [] 
           _ -> if st1 == (nHead (length st1) st2) then nTail (length st1) st2 else takeTail st1 (tail st2) 

nTail :: Int -> String -> String 
nTail n str = let rec n str = if n == 0 then str else rec (n - 1) (tail str) 
       in if (length str) < n then str else rec n str 

nHead :: Int -> String -> String 
nHead n str = let rec n str = if n == 0 then [] else (head str):(rec (n - 1) (tail str)) 
       in if (length str) < n then str else rec n str 

getValue :: String -> String -> String -> String 
getValue row field src = getField (read field) $ getRow (read row) src 

main :: IO() 
main = do 
    args <- getArgs 
    case args of 
     (path: opt1: opt2: _) -> do 
      src <- readFile path 
      putStrLn $ getValue opt1 opt2 src 
     (path: _) -> do 
      src <- readFile path 
      putStrLn $ show $ length $ lines src 

:私はこのように書き、簡単なスクリプトを持って最後に私がmeiersiのバージョン(感謝)を使用しますが、私はまだ私のエラーを見つけたい...

。それから、ByteStringに切り替えることにしました。ここに私の試みです:

import qualified Data.ByteString.Lazy as B 
import qualified Data.ByteString.Lazy.Char8 as Bc (cons, empty,unpack) 
import qualified Data.ByteString.Lazy.UTF8 as Bu (lines) 
import qualified System.Posix.Env.ByteString as Bg (getArgs) 

separator :: B.ByteString 
separator = (Bc.cons ' ' (Bc.cons ';' (Bc.cons ' ' Bc.empty))) 

getRow :: Int -> B.ByteString -> B.ByteString 
getRow n = (`B.index` n) $ Bu.lines 

getCol :: Int -> B.ByteString -> B.ByteString 
getCol n = (`B.index` n) $ wordsWithSeparator 

wordsWithSeparator :: B.ByteString -> [B.ByteString] 
wordsWithSeparator str = if B.null str then [] else (takeHead separator str):(wordsWithSeparator (takeTail separator str)) 

takeHead :: B.ByteString -> B.ByteString -> B.ByteString 
takeHead st1 st2 = if B.null st2 then B.empty else if st1 == (nHead (toInteger (B.length st1)) st2) then B.empty else B.cons (B.head st2) (takeHead st1 (B.tail st2)) 

takeTail :: B.ByteString -> B.ByteString -> B.ByteString 
takeTail st1 st2 = if B.null st2 then B.empty else if st1 == (nHead (toInteger (B.length st1)) st2) then nTail (toInteger (B.length st1)) st2 else takeTail st1 (B.tail st2) 

nTail :: Integer -> B.ByteString -> B.ByteString 
nTail n str = let rec n str = if n == 0 then str else rec (n - 1) (B.tail str) 
       in if (toInteger (B.length str)) < n then str else rec n str 

nHead :: Integer -> B.ByteString -> B.ByteString 
nHead n str = let rec n str = if n == 0 then B.empty else B.cons (B.head str)(rec (n - 1) (B.tail str)) 
       in if (toInteger (B.length str)) < n then str else rec n str 

getValue :: B.ByteString -> B.ByteString -> B.ByteString -> B.ByteString 
getValue row field = getCol (read (Bc.unpack field)) . getRow (read (Bc.unpack row)) 

main = do args <- Bg.getArgs 
      case (map (B.fromChunks . return) args) of 
                (path:opt1:opt2:_) -> do src <- B.readFile (Bc.unpack path) 
                      B.putStrLn $ getValue opt1 opt2 src 

                (path:_)   -> do src <- B.readFile (Bc.unpack path) 
                      putStrLn $ show $ length $ Bu.lines src 

これは動作しません。私はそれをデバッグできませんでした。 GHCが教えてくれるものは次のとおりです。

BETA_getlow2.hs:10:23: 
    Couldn't match expected type `GHC.Int.Int64' with actual type `Int' 
    In the second argument of `B.index', namely `n' 
    In the expression: (`B.index` n) 
    In the expression: (`B.index` n) $ Bu.lines 

BETA_getlow2.hs:13:23: 
    Couldn't match expected type `GHC.Int.Int64' with actual type `Int' 
    In the second argument of `B.index', namely `n' 
    In the expression: (`B.index` n) 
    In the expression: (`B.index` n) $ wordsWithSeparator 

ヒントがあります。

+2

コードをインラインで貼り付けると、強調表示されます。前後の空白行を残しておき、各行を少なくとも4つの空白でインデントするようにしてください。 – rampion

+0

OKです。私はポイントを与えることができないようだ... – sarfraz

答えて

2

私は自由に次の2つのサブ質問を元の質問に解釈します。

  1. あなたが投稿したスクリプトのようなスクリプトに対して、通常はどのようなハスケルコードが書かれますか?
  2. 目的の機能を効率的に実行するための適切なデータ構造は何ですか。

次のコードは、これらの2つのサブ質問に1つの答えを示しています。 textライブラリを使用して、Unicode文字のシーケンスを表します。さらに、ライブラリの高レベルAPI textを利用して、目的の機能を実装します。これにより、コードを把握しやすくなり、低レベル関数の実装における潜在的な間違いを回避できます。

{-# LANGUAGE OverloadedStrings #-} 

import qualified Data.Text as T 
import qualified Data.Text.IO as T 

import System.Environment (getArgs) 

type Table a = [[a]] 

-- | Split a text value into a text table. 
toTable :: T.Text -> Table T.Text 
toTable = map (T.splitOn " ; ") . T.lines 

-- | Retrieve a cell from a table. 
cell :: Int -> Int -> Table a -> a 
cell row col = (!! col) . (!! row) 

main :: IO() 
main = do 
    (path:rest) <- getArgs 
    src <- T.readFile path 
    case rest of 
     row : col : _ -> T.putStrLn $ cell (read row) (read col) $ toTable src 
     _    -> putStrLn $ show $ length $ T.lines src 
7
getRow n = (!!n) . lines 

は、それはあなたのようにnを使用拳の例では

getRow _ = B.index . Bu.lines 

と同じであるので、あなたはまったくnを使用していない第二版では

getRow n = B.index . Bu.lines 

との比較します(!!)演算子の引数です。 2番目のバージョンで同じことをする必要があります。それはあなたのコード内の唯一の問題ではないよう

は見えるが、私は開始するには良いポイントであると思います。

0

Yurasがあなたのために解決した最初の2つのエラーが、私は思います)。第三エラー再


words' :: B.ByteString -> [B.ByteString] 
words' str = if B.null str then B.empty else ... 

B.empty[]する必要があります。 B.empty :: B.ByteStringですが、結果は[B.ByteString]となっています。 4-7エラー再


:この場合

  • length :: [a] -> Int
  • B.length :: B.ByteString -> Int64

IはInt64代わりにIntを使用するnTailnHeadの型シグネチャを変更することになります。それでも問題が解決しない場合は、IntegralタイプにはIntegerを使用し、変換を行うにはtoIntegerを使用します。第八エラー再


入力readからStringでなければなりません。ラウンドを得ることはありません。 B.ByteStringStringに変換してreadに渡す必要があります。

(Incidently、あなたが延ByteStringに切り替え、テキストではないにしてもよろしいですか?)第9回(最終)エラー再


args :: [Data.ByteString.ByteString]厳格バイト文字列のリストNBあなたが他の場所で使っている怠惰なバイトコードではありませんが)何らかの理由でargs :: B.ByteStringのパターンマッチで期待しています。

[ByteString]のパターンマッチングは、[String]とパターンマッチングするのと同じ方法で行う必要があります。これらは両方ともリストです。

argsをタイプ[B.ByteString]map (B.fromChunks . return) argsに変換します。

関連する問題