PatternSynonymsを用いて利用側コードを変更せずにある値構築子を削除する

 こういう型がありましたが

data SExpr = Cons SExpr SExpr -- ^ Appending list and list
           | Nil              -- ^ A representation of empty list
           | Quote SExpr      -- ^ For lazy evaluation
           | AtomInt Int      -- ^ A pattern of the atom for @Int@ (primitive)
           | AtomSymbol Text  -- ^ A pattern of the atom for @Text@ (primitive)

(Lispの)シンボルを独立した表現として定義する必要が出てきました。 そうなるとこういうの

newtype Symbol = Symbol { unSymbol :: Text }
  deriving (IsString, Show, Eq)

を定義するのが普通だと思いますが、これだとシンボルの表現がS式としてのもの、Haskellの型としてのもの ……と、2つの表現が混在してしまいます。

-- その1
AtomSymbol Text
-- その2
newtype Symbol = Symbol { unSymbol :: Text }

解決策

 PatternSynonymsでpatternを定義してあげる。

data SExpr = Cons SExpr SExpr
           | Nil
           | Quote SExpr
           | AtomInt Int
           | AtomSymbol' Symbol -- Symbolを仲介させる
  deriving (Show, Eq)

-- シンボルを表す唯一の表現
newtype Symbol = Symbol { unSymbol :: Text }
  deriving (IsString, Show, Eq)

-- 無くなったAtomSymbolを付け足す
pattern AtomSymbol :: Text -> SExpr
pattern AtomSymbol x = AtomSymbol' (Symbol x)

 このコミット

でわかる通り、利用側コードは変更されてません 🐕
(もちろんpatternをimportする必要はある)

筆者プロフィール

my-latest-logo

aiya000(あいや)

せつラボ 〜圏論の基本〜」 「せつラボ2~雲と天使と関手圏~」 「矢澤にこ先輩といっしょに代数!」を書いています!

強い静的型付けとテストを用いて、バグを防ぐのが好き。Haskell・TypeScript。