首页 > 解决方案 > 字符串到术语,如果不存在术语 - 捕获错误

问题描述

处理任务,针对不同情况实施错误消息。如果没有定义的术语,则将字符串转换为术语时会卡住。

这是我的程序:

readPhone :: String->String->String->Phone
readPhone typee countrycode phoneno
    |head(countrycode)=='+'=error "+ found"
    |typee==""=error "Missing phone type"
    |otherwise=makePhone (stringToTerm typee) (toCountryCode(read countrycode)) (toPhoneNo(read phoneno))

stringToTerm :: String  -> PhoneType
stringToTerm stringEvent = read $ stringEvent ++ " " 

scanStringCC :: String -> CountryCode
scanStringCC x = if all (`elem` "0123456789") x
                 then read x :: CountryCode
                 else 0





data PhoneType = WorkLandline|PrivateMobile|WorkMobile|Other deriving (Read,Show,Eq)

newtype PlainString = PlainString String
instance Show PlainString where
  show (PlainString s) = s
--instance Num Int where
--   (*)=int_times
--   (+)=int_plus

data CountryCode = CountryCode
    {
        cCode :: Integer
    } deriving (Eq,Read)

instance Show CountryCode where
    show (CountryCode a)=(show (PlainString "+")) ++ (show a)
instance Num CountryCode where 
    CountryCode a * CountryCode b = CountryCode (a * b)
    CountryCode a + CountryCode b = CountryCode (a + b)
    CountryCode a - CountryCode b = CountryCode (a - b)
    fromInteger x = CountryCode (fromInteger x)

toCountryCode :: Integer->CountryCode
toCountryCode ccode  
    | ccode<0=error "Negative country code"
    |otherwise = CountryCode ccode


data PhoneNo = PhoneNo
    {
        pNo :: Integer
    } deriving (Read,Eq)
instance Show PhoneNo where
    show (PhoneNo a)=show a
instance Num PhoneNo where
    PhoneNo a + PhoneNo b=PhoneNo(a+b)
    PhoneNo a - PhoneNo b=PhoneNo(a-b)
    PhoneNo a * PhoneNo b=PhoneNo(a*b)
    fromInteger x = PhoneNo (fromInteger x)

toPhoneNo :: Integer -> PhoneNo
toPhoneNo pno  
    | pno<0=error "Negative phone number"
    |otherwise = PhoneNo pno

data Phone = Phone
    {
        phoneType :: PhoneType,
        countryCode :: CountryCode,
        phoneNo :: PhoneNo
    } deriving (Read,Eq)
instance Show Phone where
    show (Phone a b c)=show b ++ (show (PlainString " ")) ++ show c ++(show (PlainString "(")) ++ show a ++ (show (PlainString ")"))

makePhone :: PhoneType -> CountryCode  -> PhoneNo -> Phone
makePhone phonetype countrycode phoneno
    |otherwise = Phone phonetype countrycode phoneno

适用于readPhone "Other" "358" "2"or readPhone "" "358" "2"(最后一个给出“缺少电话类型”错误,这是正确的

但是,如果我给出readPhone "notexist "358" "2",它会显示+358 2(--- Exception: Prelude.read: no parse

如何捕捉它以显示正确的错误代码:“不正确的电话类型”

标签: haskell

解决方案


您的stringToTerm函数使用该read函数来解析 PhoneType,当它无法解析类型时,这将失败并出现错误。如果您想自己处理这种情况,您应该使用readMaybe并处理返回的Maybe

stringToTerm :: String -> PhoneType
stringToTerm stringEvent = case readMaybe stringEvent of 
  Just phoneType -> phoneType 
  Nothing -> error "Incorrect phone type"

使用错误来表示验证失败并不是非常惯用的 Haskell,我认为更好的方法是将readPhone函数的签名更改为

readPhone :: String -> String -> String -> Either String Phone

并返回Left "error message"验证失败和Right phone成功的情况。


推荐阅读