创建一个可以按任意顺序包含int和字符串的类型

时间:2012-02-24 17:49:01

标签: haskell types

我正在关注这个introduction to Haskell,而这个特定的地方(用户定义的类型2.2)我发现它特别模糊。到目前为止,我甚至不了解代码的哪一部分,以及作者的思想是什么部分。 (什么是Pt - 它从未在任何地方定义过?)。不用说,我无法执行/编译它。

作为一个让我更容易理解的例子,我想定义一个类型,它是一对Integer和一个String,或者一个String和一个Integer,但没有别的。

使用它的理论函数看起来像这样:

combine :: StringIntPair -> String
combine a b = (show a) ++ b
combine a b = a ++ (show b)

如果你需要一个有效的代码,那么这里就是CL代码:

(defgeneric combine (a b)
  (:documentation "Combines strings and integers"))

(defmethod combine ((a string) (b integer))
  (concatenate 'string a (write-to-string b)))

(defmethod combine ((a integer) (b string))
  (concatenate 'string (write-to-string a) b))

(combine 100 "500")

3 个答案:

答案 0 :(得分:8)

以下是定义数据类型的一种方法:

data StringIntPair = StringInt String Int | 
                     IntString Int String 
    deriving (Show, Eq, Ord)

请注意,我为类型StringIntPair定义了两个构造函数,它们是StringIntIntString

现在在combine

的定义中
combine :: StringIntPair -> String
combine (StringInt s i) = s ++ (show i)
combine (IntString i s) = (show i) ++ s

我正在使用模式匹配来匹配构造函数并选择正确的行为。

以下是一些使用示例:

*Main> let y = StringInt "abc" 123
*Main> let z = IntString 789 "a string"
*Main> combine y
"abc123"
*Main> combine z
"789a string"
*Main> :t y
y :: StringIntPair
*Main> :t z
z :: StringIntPair

有关示例的一些注意事项:

  • StringIntPair类型;在解释器中执行:t <expression>会显示表达式的类型
  • StringIntIntString是相同类型的构造函数
  • 竖线(|)分隔构造函数
  • 一个编写良好的函数应匹配其参数类型的每个构造函数;这就是为什么我用combine编写了两个模式,每个模式一个

答案 1 :(得分:7)

data StringIntPair = StringInt String Int
                   | IntString Int String

combine :: StringIntPair -> String
combine (StringInt s i) = s ++ (show i)
combine (IntString i s) = (show i) ++ s

所以它可以这样使用:

> combine $ StringInt "asdf" 3
"asdf3"
> combine $ IntString 4 "fasdf"
"4fasdf"

答案 2 :(得分:3)

由于Haskell是强类型的,因此您始终知道变量的类型。此外,你永远不会知道更多。例如,考虑计算列表长度的函数length。它的类型为:

length :: [a] -> Int

也就是说,它需要一个任意a的列表(尽管所有元素都具有相同的类型)并返回Int。该函数可能永远不会查看其中一个列表节点并检查其中存储的内容,因为它没有也无法获得有关存储的内容类型的任何信息。这使得Haskell非常高效,因为与典型的OOP语言(如Java)相比,不需要在运行时存储类型信息。

为了能够在一个参数中包含不同类型的变量,可以使用代数数据类型(ADT)。一个,存储StringIntIntString可以定义为:

data StringIntPair = StringInt String Int
                   | IntString Int String

您可以在参数上找到模式匹配采用的两者中的哪一个。 (请注意,您只有一个,因为字符串和in都封装在ADT中):

combine :: StringIntPair -> String
combine (StringInt str int) = str ++ show int
combine (IntString int str) = show int ++ str