对于以下代码,如何指定函数storePhone存储Int的电话号码类型(HomePhone或WorkPhone)?
type HomePhone = Int
type WorkPhone = Int
data Phone = HomePhone
| WorkPhone
storePhone :: int -> Phone
storePhone num = num
main :: IO ()
main = print $ storePhone 12345678
这个问题是我正在进行的辅助项目问题的简化版本。 我有一个模块将文件解析为相关的数据类型(也就像电话类型的样本)。所有数据都是Double,但具有不同的语义含义。在另一个模块中,我有使用数据的方法。每种方法都采用不同的数据类型排列(也称为HomePhone,WorkPhone)作为参数。我本可以制作HomePhone和WorkPhone数据类型甚至是新类型,但它会使使用数据的方法看起来很混乱,有很多模式匹配和东西。所以只是想知道我是否可以简化数据类型(又名电话),以便它更优雅,仍然是类型安全的。干杯! 我想我应该做以下几点?
type HomePhone = Int
type WorkPhone = Int
data Phone = HomePhone HomePhone
| WorkPhone WorkPhone
答案 0 :(得分:4)
目前,Phone
类型无法存储任何电话号码。它有两个构造函数,它们都采用零参数,因此不能存储任何东西。构造函数的名称与您之前定义的类型名称相同的事实并不意味着什么。
你可能想要这样的东西:
type PhoneNumber = String -- Storing phone numbers as ints is a bad idea
data PhoneType = HomePhone
| WorkPhone
deriving Show
data Phone = Phone PhoneType PhoneNumber
deriving Show
storePhone :: PhoneNumber -> PhoneType -> Phone
storePhone number typ = Phone typ number
main :: IO ()
main = print $ storePhone "12345678" HomePhone
答案 1 :(得分:4)
我认为sepp2k很好地回答了你的问题,但我会尝试解释,为什么我认为你首先遇到了这个问题。类型和值之间以及类型构造函数和值构造函数之间存在差异。
Phone = Phone
在此示例中,左侧是类型,右侧是值。请注意,类型和值都可以具有相同的名称。编译器会弄明白你的意思。基本上,在类型声明和数据声明中,您指的是类型,在函数实现中,您指的是值。
Phone = NoPhone
| Phone Int
在此示例中,NoPhone
是值,右侧Phone
是值构造函数,因为它使用类型Int
的值来创建值。左手边仍然是一种类型。
Container a = NotEmpty a
| Empty
在此示例中,Container
是一个类型构造函数,因为您可以为其提供类型Int
以获取类型 - 在本例中为类型Container Int
。 Empty
是一个值,NotEmpty
是一个值构造函数,它接受您为a
选择的任何类型的值 - 让我们调用该类型T
,以产生类型为Container T
的值。
在您的示例中,您混合了类型和值的概念。
type HomePhone = Int
type WorkPhone = Int
这表示HomePhone
和WorkPhone
只是Int
data Phone = HomePhone
| WorkPhone
这表示Phone
类型的任何内容都具有值HomePhone
或值WorkPhone
。重要的是,这些值与您之前声明的具有相同名称的类型同义词不同。
storePhone :: int -> Phone
这表示storePhone采用Int
类型的值并返回类型为Phone
的值。
storePhone num = num
这是一个问题。在这一行中,num是类型Int
的值,但是你返回num,你刚才在类型声明中说过你将返回类型Phone
的值,即值{{1 }或值HomePhone
。如果你想要愚蠢,但要符合你的类型声明,你可以做到
WorkPhone