2013-02-09 96 views
0

对于以下代码,如何指定功能storePhone将哪个电话号码类型(HomePhone或WorkPhone)存储为Int?如何使用代数数据类型的类型同义词?

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

它甚至编译?编译器可以为您提供很多有用的错误和警告信息。 – Yuras 2013-02-09 12:05:34

回答

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 
4

我觉得sepp2k回答了你的问题非常好,但我会尽量解释,为什么我认为你必须摆在首位的问题。类型和值之间以及类型构造函数和值构造函数之间是有区别的。

Phone = Phone 

在这个例子中,左边是一个类型,右边是一个值。请注意,类型和值都可以具有相同的名称。编译器会弄清楚你的意思。基本上,在类型声明和数据声明中,你的意思是类型,在函数实现中,你的意思是这个值。

Phone = NoPhone 
     | Phone Int 

在这个例子中,是NoPhone的值,并且右手侧Phone是一个值构造,因为它需要Int类型的值,使值。左侧仍然是一种类型。

Container a = NotEmpty a 
      | Empty 

在这个例子中,Container是一类的构造函数,因为你可以给它一个类型,如Int得到一个类型 - 在这种情况下将是类型Container IntEmpty是一个值,而NotEmpty是一个值构造函数,它会将您碰巧为a选择的任何类型的值(我们称之为T)生成值为Container T的值。

在你的例子中,你混合了类型和值的概念。

type HomePhone = Int 
type WorkPhone = Int 

这是说HomePhoneWorkPhone只是名称不同的类型Int

data Phone = HomePhone 
      | WorkPhone 

这是说Phone类型的东西有任何价值HomePhone或价值WorkPhone。重要的是,这些值与您之前声明的具有相同名称的同义词类型不同。

storePhone :: int -> Phone 

这是说storePhone需要Int类型的值,并返回Phone类型的值。

storePhone num = num 

这是一个问题。在这一行中,num是类型为Int的值,但是您返回num,并且您刚才在类型声明中说过,您将返回类型为Phone的值,即值HomePhone或值WorkPhone。如果你想成为傻子,但要符合你的类型声明,你可以做

storePhone num = if num > 0 then HomePhone else WorkPhone -- silly, but compiles :) 
相关问题