3
\$\begingroup\$

I'm a bit concerned about function usage. There are so many different libraries/possible ways to do something that I'm not sure if the way I'm working at the moment is reasonable, or what I could modify to have a better code.

Also, I'm searching on how to optimize this code, since for a small 25MB file the memory use goes to 800MB, and a bigger file goes OOM. What makes the memory to go so high?

Before I had strict IO writing, and was expecting to be it that caused to evaluate everything on the code, but going lazy didn't solve anything.

{-# LANGUAGE OverloadedStrings,BangPatterns #-}
import qualified Data.Attoparsec.Char8 as Ap
import Data.Attoparsec


import Control.Monad

import System.IO 
import System.Environment
import Data.Maybe
import Data.List (unzip4,zip4,foldl')
import Data.List.Split
import Data.Bits

import Numeric.FFT
--import Data.Vector.Storable (fromList)

import Data.Complex
import Data.String (fromString)
import Data.ByteString.Internal
import qualified Data.ByteString.Char8 as B
import qualified Data.ByteString.Lazy.Char8 as Bl 


newtype FourD b a = FourD  { getFourD  :: (a,a,a,b) }
instance (Show b, Show a) => Show (FourD b a) where
    show (FourD (a,b,c,d)) = "( "++show a++" , "++show b++" , "++show c++" , "++show d++" )"
instance Functor (FourD c) where  
    fmap f (FourD  (x,y,z,d)) = FourD  (f x,f y,f z,d)  

mgrav_per_bit = [ 18, 36, 71, 143, 286, 571, 1142 ]

aToG a = sign * uresult 
    where   twocomp = if a>128
                    then 256-a
                    else a
            uresult = foldr (+) 0  $ zipWith (*)   mgrav_per_bit (map ( g . testBit  twocomp) [0..7] )
            sign = if a>128
                    then -1
                    else 1
            g True = 1; g False = 0



amap f g = map FourD . uncurry4 zip4 . map4 f g . unzip4 . map getFourD
    where map4 f g (a,b,c,d) = ( f a,f  b,f  c, g d)
          uncurry4 f (a,b,c,d) = f a b c d 

splitN n x =  helper x 0
    where
    l = length x
    helper x c = if (c+n)>l 
                    then []
                    else (Prelude.take n x):(helper  (drop 1 x) (c + 1))

quare = foldr (\a b-> b+(magnitude a)) 0  

getTime :: (FourD String a)-> String
getTime (FourD (_,_,_,t)) = t    


filterAcc (FourD (x,_,_,t)) = if x > 50
                                then  (Bl.pack . B.unpack) $ "yes" `B.append` t 
                                else  Bl.pack ""   

parseAcc :: Parser (FourD B.ByteString Int)
parseAcc = do   satisfy (== 40)
                x <- Ap.decimal  
                string ","
                y <- Ap.decimal
                string ","
                z <- Ap.decimal
                string ","
                time <-  takeTill (== 41)
                return $ FourD (x,y,z,time)
                where isDigit w = w >= 48 && w <= 57
                      isNot w = w/=29

readExpr input = case parse parseAcc  input of
     Done b val -> val
     Partial p-> undefined
     Fail a b c -> undefined



fftAcross = map ( map (/32) . fft ) . splitN 32 





main = do    

    filename <- liftM head getArgs
    filehandle <- openFile "lol.txt" WriteMode
    contents <- liftM B.lines $ B.readFile filename
    Bl.hPutStr (filehandle) . Bl.concat  . map (filterAcc) . splitAndApply . convertComplex $ contents where
        convertComplex = map ( fmap( fromIntegral . aToG). readExpr )
        splitAndApply  = (amap (map (floor .quare .(drop 1) ). fftAcross) ((map  head) . splitN 32)) 


   -- B.hPutStrLn (filehandle)  . B.unlines . map (B.pack . show ) .  amap (map (floor .quare) .  (filter (/=[])) . map ( (drop 1) . (map (/32)) . fft ) . splitN 32) . map ( fmap(fromIntegral . aToG)) . map readExpr $ contents
\$\endgroup\$
1
\$\begingroup\$

You can use HLint tool to get rid of few extra parentheses, and use <$> instead of liftM:

contents <- B.lines <$> B.readFile filename

Other than that I don't see anything to be improved in your code at low level. To help with high level design there's not enough info in your question. Can you explain what do you want to achieve with your code?

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.