編集: 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
ヒントをいただければ幸いです。