Haskell函数中的模式匹配

时间:2016-04-23 05:49:50

标签: haskell pattern-matching

我有许多方法在其定义中都有样板代码,请看上面的例子。

baseRequest.delete({method: "deleteUser.req", id: id}, {}, function (response) {

如您所见,replace:: Term -> Term -> Formula -> Formula replace x y (Not f) = Not $ replace x y f replace x y (And f g) = And (replace x y f) (replace x y g) replace x y (Or f g) = Or (replace x y f) (replace x y g) replace x y (Biimp f g) = Biimp (replace x y f) (replace x y g) replace x y (Imp f g) = Imp (replace x y f) (replace x y g) replace x y (Forall z f) = Forall z (replace x y f) replace x y (Exists z f) = Exists z (replace x y f) replace x y (Pred idx ts) = Pred idx (replace_ x y ts) 函数的定义遵循一种模式。我希望函数具有相同的行为,简化他的定义,可能使用一些模式匹配,可能在参数上使用通配符replace_,如:

X

为避免以下定义:

replace x y (X f g)          = X (replace x y f) (replace x y g)

有什么办法吗?忘记函数的目的,它可以是任何东西。

3 个答案:

答案 0 :(得分:6)

如果你有许多应该以统一的方式对待的构造函数,你应该让你的数据类型反映出来。

data BinOp      = BinAnd | BinOr | BinBiimp | BinImp
data Quantifier = QForall | QExists
data Formula    = Not Formula
                | Binary BinOp Formula Formula -- key change here
                | Quantified Quantifier Formula
                | Pred Index [Formula]

现在所有二元运算符的模式匹配都更容易:

replace x y (Binary op f g) = Binary op (replace x y f) (replace x y g)

要保留现有代码,您可以启用PatternSynonyms并定义AndOr的旧版本,等等:

pattern And x y = Binary BinAnd x y
pattern Forall f = Quantified QForall f

答案 1 :(得分:3)

我不完全确定这是你在找什么,但你可以做到以下几点。我们的想法是,您可以考虑将公式抽象为另一种类型(在您的情况下通常为Term)。然后,您可以定义映射公式的含义。我试图复制你的数据定义,虽然我对Formula有一些问题 - 即所有构造函数似乎都需要另一个Formula ......

{-# LANGUAGE DeriveFunctor #-}

data Formula a
  = Not (Formula a)
  | And (Formula a) (Formula a)
  | Or (Formula a) (Formula a)
  | Biimp (Formula a) (Formula a)
  | Imp (Formula a) (Formula a)
  | Forall a (Formula a)
  | Exists a (Formula a)
  | Pred a (Formula a)
  deriving (Functor)

data Term = Term String {- However you define it, doesn't matter -} deriving (Eq)

replace :: (Functor f, Eq a) => a -> a -> f a -> f a
replace x y = fmap (\z -> if x == z then y else z)

有趣的是,现在replace函数可以应用于任何仿函数 - 它甚至可以用作列表的replace

replace 3 9 [1..6] = [1,2,9,4,5,6]

编辑作为事后的想法,如果你要实现替换样式替换公式中的术语可以被遮蔽(通常的作用域规则),你可能最终会做这样的事情:

replace' :: (Eq a) => a -> a -> Formula a -> Formula a
replace' x y f@(Forall z _) | x == z = f
replace' x y f@(Exists z _) | x == z = f
replace' x y f@(Pred z _)   | x == z = f
replace' x y formula = fmap (replace' x y) formula

这不是那么可爱,但也不是一个问题直截了当。

答案 2 :(得分:1)

Data.Functor.Foldable抽象出递归数据结构的模式:

import Data.Functor.Foldable

data FormulaF t
  = Not t
  | And t t
  | Or t t
  | Biimp t t
  | Imp t t
  | Forall A t
  | Exists A t
  | Pred B C
  deriving (Functor, Foldable, Traversable)

type Formula = Fix FormulaF

replace :: Term -> Term -> Formula -> Formula
replace x y = cata $ \case ->
  Pred idx ts -> Pred idx (replace_ x y ts)
  f -> f

顺便提一下,请注意replace x y (Forall x (f x)) = Forall x (f y)Substitution is the process of replacing all free occurences of a variable in an expression with an expression.