0

編集: Yuras と Dave4420 のアドバイスに従いました (ありがとう)。まだいくつかのエラーがあります。質問を更新しました。最後に meiersi のバージョンを使用します (ありがとうございます) が、まだエラーを見つけたいです...

次のような簡単なスクリプトがあります。

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

コンパイルして動作します。それから私はsに切り替えたいと思いました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

ヒントをいただければ幸いです。

4

3 に答える 3

7
getRow n = (!!n) . lines

と比べて

getRow n = B.index . Bu.lines

2番目のバージョンではまったく使用nしないため、同じです

getRow _ = B.index . Bu.lines

最初の例では、演算子nへの引数として使用します。(!!)2 番目のバージョンでも同じことを行う必要があります。

それがあなたのコードの唯一の問題ではないように見えますが、始めるのに良い点であることを願っています;)

于 2012-04-24T23:18:32.363 に答える
2

以下の 2 つのサブ質問を元の質問に自由に解釈します。

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

次のコードは、これら 2 つのサブ質問に対する 1 つの回答を示します。ライブラリを使用して、text一連の Unicode 文字を表します。さらに、textライブラリの高レベル API を利用して、必要な機能を実装します。これにより、コードが理解しやすくなり、低レベル関数の実装における潜在的なミスを回避できます。

{-# 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
于 2012-04-25T10:55:03.320 に答える
0

最初の 2 つのエラーは Yuras が解決したと思います。


3番目のエラーについて:

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

この場合、 の型シグネチャをnTailとの代わりにnHead使用するように変更します。それが機能しない場合は、変換を行うために使用して、すべての型で使用します。Int64IntIntegerIntegraltoInteger


8番目のエラーについて:

への入力はreadである必要がありますString。それを回避することはできません。を に変換B.ByteStringし、Stringそれを に渡す必要がありreadます。

(ちなみに、Text ではなく ByteString に切り替えてよろしいですか?)


9番目(最終)のエラーについて:

args :: [Data.ByteString.ByteString](厳密なバイト文字列のリストであり、他の場所で使用する遅延バイト文字列ではありません) しかし、args :: B.ByteString何らかの理由でパターン一致が期待されます。

でのパターン マッチ[ByteString]と同じ方法でパターン マッチを行う[String]必要があります。どちらもリストです。

args を何かの型に変換[B.ByteString]map (B.fromChunks . return) argsます。

于 2012-04-25T08:24:48.810 に答える