10

我有这种数据类型

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"

第二个工作正常,但第一个导致错误:“Parse error in pattern: exec”。你能解释一下为什么我不能以这种方式匹配构造函数:apply (exec struct) = ... 吗?

当我的数据类型中有多个构造函数并且必须分别对它们进行模式匹配时,它会导致大量样板代码。

4

5 回答 5

22

通常,如果您有多个共享数据的构造函数,那么通常最好将数据声明重构为类似

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"
于 2012-06-05T08:27:52.787 回答
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"
于 2012-06-05T08:14:42.820 回答
3

为什么?因为你只能匹配构造函数,并且exec是一种新变量。其原因之一例如如下:

data Struct2 =  Empty | Exec1 String
                      | Exec2 Int

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

怎么会有人知道你Exec1和哪个Exec2匹配?您不能在这里应用函数,因为struct无法确定实际的类型。

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

于 2012-06-05T08:23:42.493 回答
2

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

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

但是,这不会很好地扩展到更复杂的结果。

于 2012-06-05T13:16:29.337 回答
0
apply Empty = "matched empty"
apply (Exec1 _) = notEmpty
apply (Exec2 _) = notEmpty

notEmpty  = "matched Exec1 or Exec2"
于 2012-06-05T15:38:00.093 回答