2011-10-09 41 views
2
data Test = [Int] | Int 

foobar :: Test -> Int 

如果我想要的东西,像foobar的[1,2,3] = 1,foobar的1 = 1。在二郎这将是所有的如何在不同类型上进行模式匹配?

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

你有这个特定用例?或者你只是好奇? (不是说有什么不对的好奇心!)为了让你问你要争取类型系统一点点的行为,所以可能有解决问题无论你工作更哈斯克尔-Y方式。 – Zopa

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

当你说你的意思是“数据构造”“类型构造”。 – sepp2k

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 
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]作为同样的事情的两个例子是做这样的事情。你的类型越适合你解决的问题,类型分析者就可以帮助你。

+0

健全的建议。 +1。 – AndrewC

相关问题