【问题标题】:constructor pattern matching haskell构造函数模式匹配haskell
【发布时间】:2012-06-05 23:38:00
【问题描述】:

我有这种数据类型

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”。你能解释一下为什么我不能以这种方式匹配构造函数: 应用(执行结构)= ...?

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

【问题讨论】:

    标签: haskell


    【解决方案1】:

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

    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"
    

    您仍然可以对特定的执行类型进行模式匹配

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

    【讨论】:

    • 在这种情况下重新使用预定义的Maybe 类型甚至可能是个好主意。
    【解决方案2】:

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

    data Struct2 =  Empty | Exec1 String
                          | Exec2 Int
    
    apply :: Struct2 -> String
    apply Empty = "matched Empty"  
    apply (exec struct) = ??
    

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

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

    【讨论】:

      【解决方案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"
      

      【讨论】:

      • 我认为您的意思是“数据构造函数”而不是“类型构造函数”。
      【解决方案4】:

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

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

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

      【讨论】:

        【解决方案5】:
        apply Empty = "matched empty"
        apply (Exec1 _) = notEmpty
        apply (Exec2 _) = notEmpty
        
        notEmpty  = "matched Exec1 or Exec2"
        

        【讨论】:

          猜你喜欢
          • 2017-08-04
          • 2018-06-09
          • 2012-04-29
          • 2021-12-31
          • 2021-02-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-04-26
          相关资源
          最近更新 更多