如何使用代数数据类型的类型同义词?

时间:2013-02-09 11:58:36

标签: haskell types

对于以下代码,如何指定函数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 

2 个答案:

答案 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 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的值,即值{{1 }或值HomePhone。如果你想要愚蠢,但要符合你的类型声明,你可以做到

WorkPhone