例外:Prelude.read:无解析

时间:2015-11-21 13:39:48

标签: parsing haskell runtime-error

对于解析器的赋值,如果在Haskell中处理以下代码;

进口;

import ParseLib.Simple
import Prelude hiding ((<*>), (<$>),(<$),(<*))
import Data.Char
import Data.Time.Calendar hiding (Day)

数据类型;

data DateTime = DateTime { date :: Date
                     , time :: Time
                     , utc :: Bool }
deriving (Eq, Ord)

data TimeUTC = Eps | Z deriving Show


data Date = Date { year  :: Year
             , month :: Month
             , day   :: Day }
deriving (Eq, Ord)

newtype Year  = Year { unYear :: Int }  deriving (Eq, Ord)
newtype Month = Month { unMonth :: Int } deriving (Eq, Ord)
newtype Day   = Day { unDay :: Int } deriving (Eq, Ord)

data Time = Time { hour   :: Hour
             , minute :: Minute
             , second :: Second }
deriving (Eq, Ord)

newtype Hour   = Hour { unHour :: Int } deriving (Eq, Ord)
newtype Minute = Minute { unMinute :: Int } deriving (Eq, Ord)
newtype Second = Second { unSecond :: Int } deriving (Eq, Ord)

data Result = SyntaxError | Invalid DateTime | Valid DateTime deriving (Eq, Ord)

instance Show DateTime where
show = printDateTime

instance Show Result where
show SyntaxError = "date/time with wrong syntax"
show (Invalid _) = "good syntax, but invalid date or time values"
show (Valid x)   = "valid date: " ++ show x

使用所有newtypes的show实例等于此;

instance Show Year where
show (Year a) = show a

解析器看起来像这样;

-- Exercise 1
parseDateTime :: Parser Char DateTime
parseDateTime = DateTime <$> parseDate <*> parseTime <*> parseUTC

parseDigits :: Int -> Parser Char Int
parseDigits n (xs) | length f == n = [(read f :: Int, drop n xs)]
           | otherwise = []
           where f = take n xs

-- Time parsing
parseTime :: Parser Char Time
parseTime =  Time <$> parseHour <*> parseMinute <*> parseSeconds       

parseHour :: Parser Char Hour
parseHour xs | length (checkT) == 2 = [(Hour(read f :: Int), (drop 3 xs))]
         | length (checkT) == 3 = [(Hour(read f :: Int), (drop 2 xs))]
         | otherwise = []
         where f = take 3 xs
               checkT = if (head f) == 'T' then drop 1 f else f

parseMinute :: Parser Char Minute
parseMinute  = Minute <$> (parseDigits 2)

parseSeconds :: Parser Char Second
parseSeconds = Second <$> (parseDigits 2)

-- Date parsing
parseDate :: Parser Char Date
parseDate = Date <$> parseYear <*> parseMonth <*> parseDay

parseYear :: Parser Char Year
parseYear = Year <$> (parseDigits 4)

parseMonth :: Parser Char Month
parseMonth = Month <$> (parseDigits 2)

parseDay :: Parser Char Day
parseDay = Day <$> (parseDigits 2)

-- UTC parsing
parseUTC :: Parser Char Bool
parseUTC = utcToBool <$> (option ((\a -> Z) <$> satisfy (=='Z')) Eps) 

utcToBool :: TimeUTC -> Bool
utcToBool Eps = False
utcToBool Z = True

-- Exercise 2

isFinished :: [(a, [b])] -> Maybe a
isFinished [] = Nothing
isFinished ((result, rest):xs) | null rest   = Just result
                           | otherwise   = isFinished xs 

run :: Parser a b -> [a] -> Maybe b
run p s = isFinished r
      where r = p s

-- Exercise 3
printDateTime :: DateTime -> String
printDateTime (DateTime (Date year month day)(Time hour minute     second)timezone) = f year 4 ++ f month 2 ++ f day 2 ++ "T" ++ f hour 2 ++ f     minute 2 ++ f second 2 ++ endOrZ timezone
   where f s a = take (a - length (show s)) (repeat '0') ++ show s
     endOrZ False = ""
     endOrZ True = "Z"

-- Exercise 4
parsePrint s = fmap printDateTime $ run parseDateTime s

所以现在我的问题。完成练习4后,我们将接受测试&#34; parsePrint&#34;如果输入的字符串是正确的,则返回Just&#34; inputstring&#34;别的什么

所以我试着用一些给我们的字符串来测试它,我得到了以下错误;

*Main>  parsePrint "20111012T083945"
*** Exception: Prelude.read: no parse
Just "20111012T*Main> 

现在我在这里发现了一些关于相同错误的线程,这些主要是关于丢失qoutes和一个关于读取实例的错误。然而,我仍然无法弄清楚问题。

我不希望那个平坦的回答者看到它的学校作业,但如果有人能指出我正确的方向,我会非常感激,看到我一直试图想象它现在已经有几个小时了。

- 当我在这里复制代码时,缩进有点搞砸了,但我不认为那会是问题。

0 个答案:

没有答案