0

I try to parse benncoded torrent file (part of my toy project to learn Haskell) into a dedicated structure in Haskell:

import qualified Data.ByteString.Char8 as BC

data BEncode =  BString BC.ByteString
         | BInt Integer
         | BList [BEncode]
         | BDic [(BEncode, BEncode)]  <-- here is the problem I want to make it BDic [(BString, BEncode)]
         deriving (Eq,Show) 

Everything works fine but I would like to make small improvement.
BDic data constructor takes (BEncode <- this is key, BEncode ,<- this is value) list. It's too general I would like to limit keys to be only BStrings, is there a way to do this?

Here is rest of the parser:

num::P.Parser String             
num = many1 digit

bInt::P.Parser BEncode
bInt = (BInt . read) <$> (char 'i' *> num <* char 'e') 

bString :: P.Parser BEncode
bString = do n <- num
         _ <- char ':'
         BString <$> (P.take (read n))

bList :: P.Parser BEncode
bList = (BList) <$> (char 'l' *> (many1 (bInt <|> bString <|> bList)) <* char 'e')                  


dicEntry :: P.Parser (BEncode, BEncode)
dicEntry = ((,)<$>bString <*> bencodeParser)

bDic :: P.Parser BEncode
bDic = BDic<$>((char 'd' *> many1 dicEntry <* char 'e'))               

bencodeParser :: P.Parser BEncode
bencodeParser = bInt <|> bString <|> bList <|> bDic

1 Answer 1

2

BDic data constructor takes (BEncode <- this is key, BEncode ,<- this is value) list. It's too general I would like to limit keys to be only BStrings, is there a way to do this?

One way to achieve this is by changing the structure:

data BStringT = BString BC.ByteString deriving (Eq, Show)

data BEncode =  BStringT
             | BInt Integer
             | BList [BEncode]
             | BDic [(BStringT, BEncode)]  
               deriving (Eq,Show)

This way you can enforce that it will be BStringT in it's first parameter.

Sign up to request clarification or add additional context in comments.

3 Comments

Thx! I was looking for something like that, but I got another problem: bList :: P.Parser BEncode function doesn't compile: Couldn't match expected type BEncode' with actual type BStringT' Expected type: attoparsec-0.11.1.0:Data.Attoparsec.Internal.Types.Parser BC.ByteString BEncode Actual type: Parser BStringT In the second argument of (<|>)', namely bString' In the first argument of (<|>)', namely bInt <|> bString', I don't understand why...
Its the <|> function, it seems bInt<|>bString doesn't work anymore (inside bList, the same for bencodeParser function)
The first case of BEncode lacks a constructor. It should be e.g. data BEncode = BString BStringT | ...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.