简体   繁体   中英

Debugging <<loop>> error message in haskell

Hello i am encountering this error message in a Haskell program and i do not know where is the loop coming from.There are almost no IO methods so that i can hook myself to them and print the partial result in the terminal.

I start with a file , i read it and then there are only pure methods.How can i debug this ?

Is there a way to attach to methods or create a helper that can do the following:

Having a method method::a->b how can i somehow wrap it in a iomethod::(a->b)->IO (a->b) to be able to test in in GHCI (i want to insert some putStrLn -s etc ?

PS My data suffer transformations IO a(->b->c->d->......)->IO x and i do not know how to debug the part that is in the parathesis (that is the code that contains the pure methods)

Types and typeclass definitions and implementations

data TCPFile=Rfile (Maybe Readme) | Dfile  Samples | Empty
data Header=Header { ftype::Char}

newtype Samples=Samples{values::[Maybe Double]}deriving(Show)

data Readme=Readme{ maxClients::Int, minClients::Int,stepClients::Int,maxDelay::Int,minDelay::Int,stepDelay::Int}deriving(Show)

data FileData=FileData{ header::Header,rawContent::Text}

(>>?)::Maybe a->(a->Maybe b)->Maybe b
(Just t) >>? f=f t
Nothing >>? _=Nothing

class TextEncode a where
fromText::Text-> a


getHeader::TCPFile->Header
getHeader (Rfile _ ) = Header { ftype='r'}
getHeader (Dfile _ )= Header{ftype='d'}
getHeader _ = Header {ftype='e'}


instance Show TCPFile where
show (Rfile t)="Rfile " ++"{"++content++"}" where
    content=case t of
        Nothing->""
        Just c -> show c
show (Dfile c)="Dfile " ++"{"++show c ++ "}"

instance TextEncode Samples where
    fromText text=Samples  (map (readMaybe.unpack) cols) where
             cols=splitOn (pack ",") text



instance TextEncode Readme where
    fromText txt =let len= length dat
                      dat= case len of 
                            6 ->Prelude.take 6 .readData $ txt
                            _ ->[0,0,0,0,0,0] in 
            Readme{maxClients=Prelude.head dat,minClients=dat!!1,stepClients=dat!!2,maxDelay=dat!!3,minDelay=dat!!4,stepDelay=dat!!5} where




instance TextEncode TCPFile where
    fromText  = textToFile

Main

module Main where 
import Data.Text(Text,pack,unpack)
import Data.Text.IO(readFile,writeFile)
import TCPFile(TCPFile)

main::IO()
main=do
    dat<-readTcpFile "test.txt"
    print dat

readTcpFile::FilePath->IO TCPFile
readTcpFile path =fromText <$> Data.Text.IO.readFile path  

textToFile::Text->TCPFile
textToFile input=case readHeader input >>? (\h -> Just (FileData h input)) >>?  makeFile of
    Just r -> r
    Nothing ->Empty



readHeader::Text->Maybe Header
readHeader txt=case Data.Text.head txt of 
    'r' ->Just (Header{ ftype='r'})
    'd' ->Just (Header {ftype ='d'})
    _  -> Nothing

makeFile::FileData->Maybe TCPFile
makeFile fd= case ftype.header $ fd of
        'r'->Just (Rfile (Just (fromText . rawContent $ fd)))
        'd'->Just (Dfile (fromText . rawContent $ fd))
        _  ->Nothing 


readData::Text->[Int]
readData =catMaybes . maybeValues where
    maybeValues=mvalues.split.filterText "{}"

#all the methods under this line  are used in the above method

mvalues::[Text]->[Maybe Int]
mvalues arr=map (\x->(readMaybe::String->Maybe Int).unpack $ x) arr

split::Text->[Text]
split =splitOn (pack ",")

filterText::[Char]->Text->Text
filterText chars tx=Data.Text.filter (\x -> not (x `elem` chars)) tx

I want first to clean the Text from given characters , in our case }{ then split it by , .After the text is split by commas i want to parse them, and create either a Rfile which contains 6 integers , either a Dfile (datafile) which contains any given number of integers.

Input I have a file with the following content: r,1.22,3.45,6.66,5.55,6.33,2.32} and i am running runghc main 2>err.hs

Expected Output : Rfile (Just (Readme 1.22 3.45 6.66 5.55 6.33 2.32))

In the TextEncode Readme instance, len and dat depend on each other:

instance TextEncode Readme where
    fromText txt =let len= length dat
                      dat= case len of 

To debug this kind of thing, other than staring at the code, one thing you can do is compile with -prof -fprof-auto -rtsopts , and run your program with the cmd line options +RTS -xc . This should print a trace when the <<loop>> exception is raised (or if the program loops instead, when you kill it (Ctrl+C)). See the GHC manual https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/runtime_control.html#rts-flag--xc

As Li-yao Xia said part of the problem is the infinite recursion, but if you tried the following code, then the problem still remains.

instance TextEncode Readme where
    fromText txt =let len= length [1,2,3,4,5,6] --dat
                      dat= case len of 

The second issue is that the file contains decimal numbers but all the conversion function are expecting Maybe Int , changing the definitions of the following functions should give the expected results, on the other hand probably the correct fix is that the file should have integers and not decimal numbers.

readData::Text->[Double]
--readData xs = [1,2,3,4,5,6,6]
readData =catMaybes . maybeValues where
    maybeValues = mvalues . split . filterText "{}"

--all the methods under this line  are used in the above method

mvalues::[Text]->[Maybe Double]
mvalues arr=map (\x->(readMaybe::String->Maybe Double).unpack $ x) arr

data Readme=Readme{ maxClients::Double, minClients::Double,stepClients::Double,maxDelay::Double,minDelay::Double,stepDelay::Double}deriving(Show)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM