Parsing 例外:Prelude.read:无解析
如果在Haskell中处理以下代码,则为解析器赋值 进口Parsing 例外:Prelude.read:无解析,parsing,haskell,runtime-error,Parsing,Haskell,Runtime Error,如果在Haskell中处理以下代码,则为解析器赋值 进口 import ParseLib.Simple import Prelude hiding ((<*>), (<$>),(<$),(<*)) import Data.Char import Data.Time.Calendar hiding (Day) 显示与此相同的所有新类型的实例 instance Show Year where show (Year a) = show a 解析器如下所示 --
import ParseLib.Simple
import Prelude hiding ((<*>), (<$>),(<$),(<*))
import Data.Char
import Data.Time.Calendar hiding (Day)
显示与此相同的所有新类型的实例
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
现在我在这里发现了一些关于相同错误的线程,这些线程主要是关于缺少qoutes的,还有一个是关于read实例的。然而,我仍然不能真正理解这个问题
我不指望这位精疲力竭的安瑟尔会认为这是学校的作业,但如果有人能给我指出正确的方向,我会非常感激,因为我已经花了几个小时试图弄明白这一点
--当我在这里复制代码时,缩进有点混乱,但我认为这不是问题。我认为问题就在这里:
parseHour xs | length(checkT)==2=[(Hour(读f::Int),(drop 3xs))]
-在读取f
部分-请参阅:f
仍将包含'T'
,因此您应该执行读取checkT::Int
而不是下一行也有点奇怪:|长度(checkT)==3=[(小时(读取f::Int),(下降2 x))]
-为什么您要将3位数字读入Hour
,但只从输入中读入2位?总的来说,我会编写一个解析器,使用可选的T
(()
返回值就可以了),然后使用这一位加上小时部分已有的parseDigits
-- 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
*Main> parsePrint "20111012T083945"
*** Exception: Prelude.read: no parse
Just "20111012T*Main>