简体   繁体   English

构造函数模式匹配haskell

[英]constructor pattern matching haskell

I have this data type 我有这个数据类型

data Struct val =  Empty | Exec1 val
                         | Exec2 val 

And two dummy functions 和两个虚拟功能

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"

Second one is working fine, but the first one is causing error: "Parse error in pattern: exec". 第二个工作正常,但第一个导致错误:“在模式中解析错误:exec”。 Can you plase explain why can't I match on constructor this way: apply (exec struct) = ... ? 您能否解释一下为什么我不能以这种方式在构造函数上进行匹配:apply(exec struct)= ...?

It's causing a lot of boilerplate code when I have multiple constructors in my datatype and must pattern match them all separately. 当我的数据类型中有多个构造函数并且必须分别对它们进行模式匹配时,这会导致很多样板代码。

In general, if you have several constructors that share data, then it's usually better to refactor the data declaration to something like 通常,如果您有多个共享数据的构造函数,那么通常最好将数据声明重构为类似

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

Now you can pattern match in apply like this 现在您可以像这样在模式匹配中apply

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

and you can still also pattern match to a specific Exec-type 而且您仍然可以将模式匹配到特定的Exec类型

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

"exec" is not a type constructor and you can only use those in pattern matching. “ exec”不是类型构造函数,您只能在模式匹配中使用它们。

What you can do is 你能做的是

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"

Why? 为什么? Because you can only match constructors, and exec is kind of a new variable. 因为您只能匹配构造函数,所以exec是一个新变量。 One reason for this is for example the following: 造成这种情况的原因之一如下:

data Struct2 =  Empty | Exec1 String
                      | Exec2 Int

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

How should anyone know which of Exec1 and Exec2 you are matching? 谁能知道您要匹配的Exec1Exec2 You couldn't apply functions here, since the actual type of struct couldn't be determined. 您无法在此处应用函数,因为无法确定struct的实际类型。

If you want to reduce the pattern matching, there are a number of ways, from using case , over different data implementation (like @Karolis suggested) and helper functions to higher level constructs with more complex types. 如果要减少模式匹配,可以使用多种方法,从使用case到不同的data实现(如建议的@Karolis)和helper函数,再到具有更复杂类型的更高级别的构造。 But that's an endless topic. 但这是一个无休止的话题。

In your particular case you can do the following: 在您的特定情况下,您可以执行以下操作:

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

This will not scale nicely to more complicated results though. 但是,这将无法很好地扩展到更复杂的结果。

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

notEmpty  = "matched Exec1 or Exec2"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM