构造函数模式匹配haskell

use*_*699 7 haskell

我有这种数据类型

data Struct val =  Empty | Exec1 val
                         | Exec2 val 
Run Code Online (Sandbox Code Playgroud)

还有两个虚函数

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"
Run Code Online (Sandbox Code Playgroud)

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

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

sha*_*ang 20

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

data Struct val = Empty | NonEmpty StructType val
data StructType = Exec1 | Exec2
Run Code Online (Sandbox Code Playgroud)

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

apply :: Struct -> String
apply (Empty) = "matched Empty"  
apply (NonEmpty exec struct) = "matched Exec1 or Exec2"
Run Code Online (Sandbox Code Playgroud)

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

apply' :: Struct val -> String
apply' (Empty)   = "matched Empty"  
apply' (NonEmpty Exec1 _) = "matched Exec1"
apply' (NonEmpty Exec2 _) = "matched Exec2"
Run Code Online (Sandbox Code Playgroud)

  • 在这种情况下重新使用预定义的"Maybe"类型甚至可能是个好主意. (2认同)

phi*_*ler 3

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

data Struct2 =  Empty | Exec1 String
                      | Exec2 Int

apply :: Struct2 -> String
apply Empty = "matched Empty"  
apply (exec struct) = ??
Run Code Online (Sandbox Code Playgroud)

别人怎么知道你Exec1和谁Exec2是匹配的?struct您无法在这里应用函数,因为无法确定 的实际类型。

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