对于解析器的赋值,如果在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和一个关于读取实例的错误。然而,我仍然无法弄清楚问题。
我不希望那个平坦的回答者看到它的学校作业,但如果有人能指出我正确的方向,我会非常感激,看到我一直试图想象它现在已经有几个小时了。
- 当我在这里复制代码时,缩进有点搞砸了,但我不认为那会是问题。