构造函数模式匹配haskell

时间:2012-06-05 08:10:07

标签: haskell

我有这种数据类型

data Struct val =  Empty | Exec1 val
                         | Exec2 val 

两个虚拟函数

apply :: Struct -> String
apply (Empty) = "matched Empty"  
apply (exec struct) = "matched Exec1 or Exec2"              

apply' :: Struct val -> String
apply' (Empty)   = "matched Empty"  
apply' (Exec1 _) = "matched Exec1"
apply' (Exec2 _) = "matched Exec2"

第二个工作正常,但第一个导致错误:“模式中的解析错误:exec”。你可以解释为什么我不能这样在构造函数上匹配: apply(exec struct)= ...?

当我的数据类型中有多个构造函数时,它会导致很多样板代码,并且必须单独匹配它们。

5 个答案:

答案 0 :(得分:19)

一般来说,如果你有几个共享数据的构造函数,那么通常最好将数据声明重构为

data Struct val = Empty | NonEmpty StructType val
data StructType = Exec1 | Exec2

现在你可以在apply这样的模式匹配

apply :: Struct -> String
apply (Empty) = "matched Empty"  
apply (NonEmpty exec struct) = "matched Exec1 or Exec2"

并且您仍然可以将模式匹配到特定的Exec类型

apply' :: Struct val -> String
apply' (Empty)   = "matched Empty"  
apply' (NonEmpty Exec1 _) = "matched Exec1"
apply' (NonEmpty Exec2 _) = "matched Exec2"

答案 1 :(得分:3)

“exec”不是类型构造函数,您只能在模式匹配中使用它们。

你能做的是

data Struct val =  Empty | Exec Int val

apply :: Struct -> String
apply (Empty) = "matched Empty"  
apply (Exec _ _) = "matched Exec1 or Exec2"              

apply' :: Struct val -> String
apply' (Empty)   = "matched Empty"  
apply' (Exec 1 _) = "matched Exec1"
apply' (Exec 2 _) = "matched Exec2"

答案 2 :(得分:3)

为什么呢?因为你只能匹配构造函数,exec是一个新变量。其中一个原因是例如:

data Struct2 =  Empty | Exec1 String
                      | Exec2 Int

apply :: Struct2 -> String
apply Empty = "matched Empty"  
apply (exec struct) = ??

如何知道您匹配的Exec1Exec2中的哪一个?您无法在此处应用函数,因为无法确定struct的实际类型。

如果你想减少模式匹配,有很多方法,从使用case,到不同的data实现(如@Karolis建议)和辅助函数到更高级别的结构更多复杂的类型。但那是一个无穷无尽的话题。

答案 3 :(得分:1)

在您的特定情况下,您可以执行以下操作:

apply :: Struct -> String
apply Empty = "matched Empty"  
apply _     = "matched Exec1 or Exec2"

虽然这不会很好地扩展到更复杂的结果。

答案 4 :(得分:0)

apply Empty = "matched empty"
apply (Exec1 _) = notEmpty
apply (Exec2 _) = notEmpty

notEmpty  = "matched Exec1 or Exec2"