在typeclass中重载Show和Num会使执行无限期挂起



我在Haskell上做作业,几乎解决了它。感觉我错过了最后一步,但我无法指出,我做错了什么。

首先我的任务:

现在,不使用类型同义词,而是定义数据类型CountryCode和PhoneNo,这样它们都有一个接受整数的值构造函数。导出PhoneType的Eq、Ord和Show的实例。导出CountryCode和PhoneNo的Eq和Ord实例,并为它们制作Show实例,以便:CountryCode:在数字前面打印"+"。电话号码:只打印号码。为这两个函数(toCountryCode和toPhoneNo(创建一个函数,该函数接受一个Integer,如果该整数为负数,则抛出一个错误,否则它将创建该值。

如果CountryCode为负数,则错误应为"负国家代码";如果PhoneNo为负,则错误应为"否";负电话号码";你应该按照这些来通过自动测试。

再次使用记录语法,为只有一个带字段的值构造函数的电话号码定义电话类型

phoneType :: PhoneType,
countryCode :: CountryCode, (This time the type defined as above)
phoneNo :: PhoneNo. (This time the type defined as above)

为记录导出Eq和Ord的实例,但为Show使其";漂亮的印刷品;此形式的信息:例如+358 123456789(WorkLandline(

现在我的任务:

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 :: Int
} deriving (Read,Eq)
instance Show CountryCode where
show (CountryCode a)=(show (PlainString "+")) ++ (show a)
instance Num CountryCode where 
(*) a b=a*b 
(+) a b=a+b 
(-) a b=a-b
fromInteger x=fromInteger x 
toCountryCode :: Int->CountryCode
toCountryCode ccode  
| ccode<0=error "Negative country code"
|otherwise = CountryCode ccode

data PhoneNo = PhoneNo
{
pNo :: Int
} deriving (Read,Eq)
instance Show PhoneNo where
show (PhoneNo a)=show a
instance Num PhoneNo where
(*) a b=a*b
(+) a b=a+b
(-) a b=a-b
fromInteger x= fromInteger x
toPhoneNo :: Int -> 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 a
makePhone :: PhoneType -> CountryCode  -> PhoneNo -> Phone
makePhone phonetype countrycode phoneno
|otherwise = Phone phonetype countrycode phoneno

这个版本有点适用于:makePhone其他1 1,显示其他

但是,如果我将其修改为:show(电话a b c(=显示b或者像任务中所要求的那样使sane显示-程序无限期挂起。显示c也是如此

我做错了什么?

实现,如:

instance Num CountryCode where 
(*) a b = a*b 
(+) a b = a+b 
(-) a b = a-b
fromInteger x = fromInteger x

没有多大意义,因为您在这里定义了可以将两个CountryCode添加在一起,通过将它们添加在一起。。。这就导致了中缀递归。

您可以通过拆包封装在CountryCode数据构造函数中的值来定义加法、乘法等,执行算术运算,然后将其封装在CountryCode数据构造函数中:

instance Num CountryCode where 
CountryCodea *CountryCodeb =CountryCode(a * b)
CountryCodea +CountryCodeb =CountryCode(a + b)
CountryCodea -CountryCodeb =CountryCode(a - b)
fromInteger x =CountryCode(fromInteger x)

instance Num PhoneNo也是如此。

您可以使用GeneralizedNewtypeDeriving来派生以下实例,但它们必须是newtype才能工作:

  • Show PlainString
  • Num CountryCode
  • Show PhoneNoNum PhoneNo

我建议使用DerivingStrategies来明确您使用的派生方法:stock使用GHC内置的派生机制,newtype使用底层类型的实例(Show StringShow IntNum Int(。

{-# Language DerivingStrategies         #-}
{-# Language GeneralizedNewtypeDeriving #-}
newtype CountryCode = CountryCode { cCode :: Int }
deriving
stock (Eq, Read)
deriving
newtype Num
newtype PlainString = PlainString String
deriving
newtype Show
newtype PhoneNo = PhoneNo { pNo :: Int }
deriving
stock (Eq, Read)
deriving
newtype (Num, Show)

最新更新