【问题标题】:How to use type synonyms with algebraic data type?如何将类型同义词与代数数据类型一起使用?
【发布时间】:2013-02-10 06:17:02
【问题描述】:

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

【问题讨论】:

  • 它甚至可以编译吗?编译器可以在错误和警告中为您提供很多有用的信息。

标签: haskell types


【解决方案1】:

在其当前形式中,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

【讨论】:

    【解决方案2】:

    我认为 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 或值 @ 987654350@。如果你想傻,但符合你的类型声明,你可以这样做

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多