如何在不同类型上进行模式匹配?

时间:2011-10-09 15:11:21

标签: haskell

data Test = [Int] | Int

foobar :: Test -> Int

如果我想要像foobar [1,2,3] = 1和foobar 1 = 1这样的东西怎么办?在erlang中它会是

foobar(X) when is_list(X) -> hd(X);
foobar(X) -> X.

3 个答案:

答案 0 :(得分:13)

首先,您的数据声明无效。在Haskell中,您必须使用数据构造函数启动数据声明,稍后将对其进行匹配。例如,您的类型Test将被写入

data Test = TLst [Int] | TInt Int

现在你可以简单地匹配类型构造函数;它的字段是列表或int,具体取决于您匹配的构造函数:

foobar :: Test -> Int
foobar (TLst (x:xs)) = x
foobar (TLst [])     = error "empty list passed to foobar"
foobar (TInt x)      = x

答案 1 :(得分:7)

另一种方法是使用类型类,如下所示:

class Test a where 
    foobar a -> Int

instance Test Int where
    foobar x = x

instance Test [Int] where
    foobar [] = error "Empty list"
    foobar (x:_) = x

模式匹配在这里是隐式的 - 传递给foobar的类型决定了我们选择的实例。

但你可能不希望做这种事情,除非你的问题中存在对称性,这使得将Int和[Int]视为同类事物的两个例子是明智的。你的类型越匹配你正在解决的问题,类型检查员就越能帮助你。

答案 2 :(得分:3)

首先,这不是有效的Haskell语法:

data Test = [Int] | Int   -- this doesn't work

替代方案需要自己的构造函数。所以这是有效的:

data Test = TestA [Int] | TestB Int

然后你可以像这样模式匹配:

foobar :: Test -> Int
foobar (TestA listOfInt) = length listOfInt
foobar (TestB int)       = int