Parsing 例外:Prelude.read:无解析

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 解析器如下所示 --

如果在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
解析器如下所示

-- 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>