【问题标题】:Pattern matching Data.Sequence like lists模式匹配 Data.Sequence 类似列表
【发布时间】:2026-01-02 12:20:03
【问题描述】:

我使用Data.Sequence 代替列表以获得更好的性能。使用列表,我们可以执行以下操作

foo :: [Int] -> Int
foo [] m = m
foo (x:xs) m = ...

如何使用Data.Sequence 来实现这一点。我尝试了以下方法:

foo:: S.Seq Int -> Int
foo S.empty m = m
foo (x S.<: xs) m = ...

我认为解决方案涉及使用S.viewlS.viewr,但似乎无法弄清楚如何使用。

【问题讨论】:

    标签: haskell pattern-matching abstract-data-type pattern-synonyms


    【解决方案1】:

    ViewPatterns 可能是去这里的方式。您的代码不起作用,因为您需要首先在您的Seq 上调用viewlviewr 以获得ViewLViewR 类型的内容。 ViewPatterns 可以很好地处理这个问题:

    {-# LANGUAGE ViewPatterns #-}
    
    foo (S.viewl -> S.EmptyL)    = ... -- empty on left
    foo (S.viewl -> (x S.:< xs)) = ... -- not empty on left
    

    这相当于:

    foo seq = case S.viewl seq of
        S.EmptyL    -> ...
        (x S.:< xs) -> ...
    

    【讨论】:

    • 你是说S.EmptyL
    【解决方案2】:

    从 GHC 7.8 开始,您可以将 pattern synonymsview patterns 一起用于此目的:

    {-# LANGUAGE ViewPatterns, PatternSynonyms #-}
    
    import qualified Data.Sequence as Seq
    
    pattern Empty   <- (Seq.viewl -> Seq.EmptyL)
    pattern x :< xs <- (Seq.viewl -> x Seq.:< xs)
    pattern xs :> x <- (Seq.viewr -> xs Seq.:> x)
    

    从 GHC 7.10 开始,您还可以将其设为双向模式同义词,以便 Empty(:&lt;)(:&gt;) 也可以用作“构造函数”:

    {-# LANGUAGE ViewPatterns, PatternSynonyms #-}
    
    import qualified Data.Sequence as Seq
    
    pattern Empty   <- (Seq.viewl -> Seq.EmptyL)  where Empty = Seq.empty
    pattern x :< xs <- (Seq.viewl -> x Seq.:< xs) where (:<)  = (Seq.<|) 
    pattern xs :> x <- (Seq.viewr -> xs Seq.:> x) where (:>)  = (Seq.|>) 
    

    【讨论】:

    • 太棒了,我不知道这会进入 7.10。为什么GHC ticket 仍然对它开放?
    • @AndrásKovács:呃……我把它打开了,因为该票证中的匹配器与构建器类型上下文问题尚未完全解决。