PatternSynonyms
在這個例子中,讓我們看一下 Data.Sequence
暴露的介面,讓我們看看如何使用模式同義詞來改進它。所述 Seq
型別是,在內部,使用一個資料型別複雜表示實現良好的漸近複雜用於各種操作,最值得注意的是兩個 O(1)
(未)consing 和(UN)snocing。
但是這種表示是笨拙的,並且它的一些不變數不能在 Haskell 的型別系統中表達。因此,Seq
型別作為抽象型別暴露給使用者,以及保持不變的訪問器和建構函式,其中包括:
empty::Seq a
(<|) :: a -> Seq a -> Seq a
data ViewL a = EmptyL | a :< (Seq a)
viewl::Seq a -> ViewL a
(|>) :: Seq a -> a -> Seq a
data ViewR a = EmptyR | (Seq a) :> a
viewr::Seq a -> ViewR a
但是使用這個介面可能有點麻煩:
uncons::Seq a -> Maybe (a, Seq a)
uncons xs = case viewl xs of
x :< xs' -> Just (x, xs')
EmptyL -> Nothing
我們可以使用檢視模式進行一些清理:
{-# LANGUAGE ViewPatterns #-}
uncons::Seq a -> Maybe (a, Seq a)
uncons (viewl -> x :< xs) = Just (x, xs)
uncons _ = Nothing
使用 PatternSynonyms
語言擴充套件,我們可以通過允許模式匹配假裝我們有一個 consoc 或 snoc-list 來提供更好的介面:
{-# LANGUAGE PatternSynonyms #-}
import Data.Sequence (Seq)
import qualified Data.Sequence as Seq
pattern Empty::Seq a
pattern Empty <- (Seq.viewl -> Seq.EmptyL)
pattern (:<) :: a -> Seq a -> Seq a
pattern x :< xs <- (Seq.viewl -> x Seq.:< xs)
pattern (:>) :: Seq a -> a -> Seq a
pattern xs :> x <- (Seq.viewr -> xs Seq.:> x)
這使我們能夠以非常自然的方式編寫 uncons
:
uncons::Seq a -> Maybe (a, Seq a)
uncons (x :< xs) = Just (x, xs)
uncons _ = Nothing