我有这种数据类型
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)= ...?
当我的数据类型中有多个构造函数时,它会导致很多样板代码,并且必须单独匹配它们。
答案 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) = ??
如何知道您匹配的Exec1
和Exec2
中的哪一个?您无法在此处应用函数,因为无法确定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"